==============================翻譯==============================
運作該應用程式并浏覽到
Movies
控制器通過将/Movies追加到您的浏覽器的位址欄中的 URL。将滑鼠指針懸停在編輯連結,看到它連結到的 URL。
編輯連結是由Views\Movies\Index.cshtml視圖中的
Html.ActionLink
方法生成的:
@Html.ActionLink("Edit", "Edit", new { id=item.ID })
Html
對象是一個幫助器,公開使用System.Web.Mvc.WebViewPage基類的類上的屬性。利用幫助程式的
ActionLink
方法,可以很容易地動态生成相應的 HTML 超連結,以連結到控制器上的操作方法。
ActionLink
方法的第一個參數是要呈現的連結文本 (例如,
<a>Edit Me</a>
)。第二個參數是要調用的操作方法的名稱。最後一個參數是資料生成的路由 (在本例中,ID 為 4 的) 中的匿名對象。
上圖中所示的生成的連結是http://localhost:xxxxx/電影/編輯/4。預設的路由 (在App_Start\RouteConfig.cs建立) 采用 URL 模式
{controller}/{action}/{id}
。是以,ASP.NET 将http://localhost:xxxxx/電影/編輯/4轉化到
Movies
控制器與參數
ID
等于 4 的
Edit
操作方法的請求。檢查App_Start\RouteConfig.cs檔案中的以下代碼。
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index",
id = UrlParameter.Optional }
);
}
您還可以傳遞使用查詢字元串的操作方法參數。例如,URLhttp://localhost:xxxxx/電影/編輯? ID = 4還将參數
ID
為 4 的傳遞給
Edit
Movies
控制器的操作方法。
打開
Movies
控制器。兩個
Edit
操作方法如下所示。
//
// GET: /Movies/Edit/5
public ActionResult Edit(int id = 0)
{
Movie movie = db.Movies.Find(id);
if (movie == null)
{
return HttpNotFound();
}
return View(movie);
}
//
// POST: /Movies/Edit/5
[HttpPost]
public ActionResult Edit(Movie movie)
{
if (ModelState.IsValid)
{
db.Entry(movie).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(movie);
}
注意第二個
Edit
操作方法的前面是
HttpPost
屬性。此屬性指定的
Edit
方法的重載可以僅為 POST 請求調用。您可以将
HttpGet
屬性應用于第一種編輯方法,但這并不必要,因為它是預設值。(我們會參閱于隐式地為
HttpGet
方法配置設定的
HttpGet
屬性的操作方法。
HttpGet
Edit
方法擷取電影 ID 參數、 查找電影使用實體架構
Find
方法,并傳回到編輯視圖的標明的影片。ID 參數指定預設值為零,如果不帶參數調用該
Edit
的方法。如果不能找到一部電影,則傳回HttpNotFound。當腳手架系統建立的編輯視圖時,它審查
Movie
類并建立呈現
<label>
和
<input>
元素的每個屬性的類的代碼。下面的示例顯示了編輯視圖生成的:
@model MvcMovie.Models.Movie
@{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Movie</legend>
@Html.HiddenFor(model => model.ID)
<div class="editor-label">
@Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Title)
@Html.ValidationMessageFor(model => model.Title)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.ReleaseDate)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.ReleaseDate)
@Html.ValidationMessageFor(model => model.ReleaseDate)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Genre)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Genre)
@Html.ValidationMessageFor(model => model.Genre)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Price)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Price)
@Html.ValidationMessageFor(model => model.Price)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
注意視圖模闆如何在檔案的頂部有一
@model MvcMovie.Models.Movie
聲明 — — 這指定視圖期望的模型視圖模闆的類型
Movie
類型.
基架的代碼使用的幫助器方法的幾種簡化的 HTML 标記。
Html.LabelFor
helper 顯示字段 ("标題"、"ReleaseDate"、"流派"或"價格") 的名稱。
Html.EditorFor
幫助器将呈現 HTML
<input>
元素。
Html.ValidationMessageFor
幫助器将顯示與該屬性相關聯的任何驗證消息。
運作該應用程式,然後定位到/Movies的 URL。單擊編輯連結。在浏覽器中檢視頁面源代碼。表單的表單元素的 HTML 如下所示。
<form action="/Movies/Edit/4" method="post"> <fieldset>
<legend>Movie</legend>
<input data-val="true" data-val-number="The field ID must be a number." data-val-required="The ID field is required." id="ID" name="ID" type="hidden" value="4" />
<div class="editor-label">
<label for="Title">Title</label>
</div>
<div class="editor-field">
<input class="text-box single-line" id="Title" name="Title" type="text" value="Rio Bravo" />
<span class="field-validation-valid" data-valmsg-for="Title" data-valmsg-replace="true"></span>
</div>
<div class="editor-label">
<label for="ReleaseDate">ReleaseDate</label>
</div>
<div class="editor-field">
<input class="text-box single-line" data-val="true" data-val-date="The field ReleaseDate must be a date." data-val-required="The ReleaseDate field is required." id="ReleaseDate" name="ReleaseDate" type="text" value="4/15/1959 12:00:00 AM" />
<span class="field-validation-valid" data-valmsg-for="ReleaseDate" data-valmsg-replace="true"></span>
</div>
<div class="editor-label">
<label for="Genre">Genre</label>
</div>
<div class="editor-field">
<input class="text-box single-line" id="Genre" name="Genre" type="text" value="Western" />
<span class="field-validation-valid" data-valmsg-for="Genre" data-valmsg-replace="true"></span>
</div>
<div class="editor-label">
<label for="Price">Price</label>
</div>
<div class="editor-field">
<input class="text-box single-line" data-val="true" data-val-number="The field Price must be a number." data-val-required="The Price field is required." id="Price" name="Price" type="text" value="2.99" />
<span class="field-validation-valid" data-valmsg-for="Price" data-valmsg-replace="true"></span>
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
</form>
<input>
元素在其
action
屬性設定為發送到/Movies/EditURL 的 HTML
<form>
元素。窗體資料将張貼到伺服器,單擊編輯按鈕時。
處理 POST 請求
下面的清單顯示
HttpPost
版本的
Edit
操作方法。
[HttpPost]
public ActionResult Edit(Movie movie)
{
if (ModelState.IsValid)
{
db.Entry(movie).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(movie);
}
ASP.NET MVC 中的模型聯程式設計式已過帳的窗體值并建立一個
Movie
對象,作為
movie
參數傳遞。
ModelState.IsValid
方法驗證送出表單中的資料可以用于修改 (編輯或更新)
Movie
對象。如果資料是有效的電影資料将儲存到的
Movies
集合
db(MovieDBContext
instance)。通過調用
SaveChanges
方法
MovieDBContext
的情況下,新的電影資料儲存到資料庫。儲存資料之後,代碼把使用者重定向到的
MoviesController
類,其中顯示了
Index
操作方法的電影收藏,包括剛才所做的更改。
如果發送的值不是有效的系統會将他們重新顯示在窗體中。Edit.cshtml視圖模闆中的
Html.ValidationMessageFor
傭工照顧顯示相應的錯誤消息。
注意要支援 jQuery 驗證為非英語區域設定,使用逗号 (",") 十進制的小數點,你必須包括globalize.js和你具體cultures/globalize.cultures.js檔案 (從https://github.com/jquery/globalize) 和 JavaScript 可以使用
Globalize.parseFloat
。下面的代碼示範對要與"FR-FR"文化工作的 Views\Movies\Edit.cshtml 檔案的修改:
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
<script src="~/Scripts/globalize.js"></script>
<script src="~/Scripts/globalize.culture.fr-FR.js"></script>
<script>
$.validator.methods.number = function (value, element) {
return this.optional(element) ||
!isNaN(Globalize.parseFloat(value));
}
$(document).ready(function () {
Globalize.culture('fr-FR');
});
</script>
<script>
jQuery.extend(jQuery.validator.methods, {
range: function (value, element, param) {
//Use the Globalization plugin to parse the value
var val = $.global.parseFloat(value);
return this.optional(element) || (
val >= param[0] && val <= param[1]);
}
});
</script>
}
十進制的字段可能需要一個逗号,不是小數點。作為臨時的修複程式,可以将全球化元素添加到項目根 web.config 檔案。下面的代碼顯示設定為美國英語的文化全球化元素。
<system.web>
<globalization culture ="en-US" />
<!--elements removed for clarity-->
</system.web>
所有
HttpGet
方法都遵循類似的模式。他們獲得一個電影對象 (或對象的清單,如
Index
),并将模型傳遞給視圖。
Create
方法将一個空影片對象傳遞給建立視圖。建立、 編輯、 删除或以其他方式修改資料的方法這樣做
HttpPost
重載的方法。修改 HTTP GET 方法中的資料是安全風險,在部落格郵政條目中所述ASP.NET MVC 提示 #46 — — 不使用删除連結,因為它們建立安全漏洞。在 GET 方法中修改資料也違反了 HTTP 的最佳做法和建築的其餘部分圖案,指定 GET 請求不應更改應用程式的狀态。換句話說,執行 GET 操作,應該是安全的操作,沒有任何副作用,不會修改您的持久化的資料。
添加一個搜尋方法和搜尋視圖
在本節中,您将添加允許您搜尋電影按類型排列的主題或名稱
SearchIndex
操作方法。這将可使用/Movies/SearchIndex的 URL。該請求将顯示一個 HTML 表單,包含輸入的元素,使用者可以輸入要搜尋的一部電影。當使用者送出窗體時,在操作方法将擷取使用者張貼的搜尋值和使用的值在資料庫中搜尋。
顯示 SearchIndex 窗體
通過将
SearchIndex
操作方法添加到現有的
MoviesController
類開始。該方法将傳回包含 HTML 表單的視圖。下面是代碼:
public ActionResult SearchIndex(string searchString)
{
var movies = from m in db.Movies
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
return View(movies);
}
SearchIndex
方法的第一行建立以下的LINQ查詢,以選擇看電影:
var movies = from m in db.Movies
select m;
這裡隻是定義了一個查詢,并沒有真正對資料存儲運作查詢。
如果
searchString
參數包含一個字元串,修改電影查詢要篩選的值的搜尋字元串,使用以下代碼:
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
s => s.Title
上面的代碼是一個Lambda 表達式。例如,其中的方法在上面的代碼中使用标準查詢運算符方法的參數的方法基于LINQ查詢使用,lambda。當他們被定義或被修改的調用 (如
Where
或
OrderBy
方法時不執行 LINQ 查詢。相反,延遲查詢執行,這意味着表達式的計算延遲,直到其實作的價值實際上來反複或
ToList
方法調用。在
SearchIndex
示例中,SearchIndex 視圖中執行查詢。有關延遲的查詢執行的詳細資訊,請參閱查詢執行.
現在,您可以實作
SearchIndex
視圖,以便向使用者顯示該窗體。在
SearchIndex
方法内右鍵單擊,然後單擊添加視圖。在添加視圖對話框中,指定您要将
Movie
對象傳遞到視圖模闆作為其模型類。在基架模闆清單中,選擇清單,然後單擊添加.
當您單擊添加按鈕時,建立Views\Movies\SearchIndex.cshtml視圖模闆。因為您選擇 (啟用了基架) 在腳手架模闆清單中,Visual Studio 将自動生成的清單視圖中的一些預設标記。腳手架建立 HTML 表單。它審查
Movie
類,并建立用于呈現
<label>
元素的類的每個屬性的代碼。下面的清單顯示了生成建立視圖:
@model IEnumerable<MvcMovie.Models.Movie>
@{
ViewBag.Title = "SearchIndex";
}
<h2>SearchIndex</h2>
<p>
@Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
<th>
Title
</th>
<th>
ReleaseDate
</th>
<th>
Genre
</th>
<th>
Price
</th>
<th></th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
@Html.ActionLink("Details", "Details", new { id=item.ID }) |
@Html.ActionLink("Delete", "Delete", new { id=item.ID })
</td>
</tr>
}
</table>
運作該應用程式,然後定位到/Movies/SearchIndex。如追加查詢字元串
?searchString=ghost
到的 URL。顯示已篩選的電影。
如果您更改的
SearchIndex
方法,有一個名為
id
參數的簽名,
id
參數将比對
{id}
占位符在Global.asax檔案中設定的預設路由。
{controller}/{action}/{id}
SearchIndex
的原始方法看起來像這樣::
public ActionResult SearchIndex(string searchString)
{
var movies = from m in db.Movies
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
return View(movies);
}
修改後的
SearchIndex
方法将如下所示:
public ActionResult SearchIndex(string id)
{
string searchString = id;
var movies = from m in db.Movies
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
return View(movies);
}
現在,可以将搜尋标題作為路由資料 (URL 部分) 而不是作為查詢字元串值傳遞。
但是,你不能指望使用者修改 URL,每次他們想要搜尋的一部電影。是以,現在您将添加使用者界面,幫助他們篩選的電影。如果您更改了的
SearchIndex
方法來測試如何傳遞路線綁定 ID 參數的簽名,更改它以便您
SearchIndex
方法采用一個名為
searchString
的字元串參數:
public ActionResult SearchIndex(string searchString)
{
var movies = from m in db.Movies
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
return View(movies);
}
打開Views\Movies\SearchIndex.cshtml檔案,并隻在
@Html.ActionLink("Create New", "Create")
之後, 添加以下内容:
@using (Html.BeginForm()){
<p> Title: @Html.TextBox("SearchString")<br />
<input type="submit" value="Filter" /></p>
}
下面的示例示範具有添加篩選标記的Views\Movies\SearchIndex.cshtml檔案的一部分。
@model IEnumerable<MvcMovie.Models.Movie>
@{
ViewBag.Title = "SearchIndex";
}
<h2>SearchIndex</h2>
<p>
@Html.ActionLink("Create New", "Create")
@using (Html.BeginForm()){
<p> Title: @Html.TextBox("SearchString") <br />
<input type="submit" value="Filter" /></p>
}
</p>
Html.BeginForm
幫助器建立開放
<form>
标記。在使用者通過單擊篩選按鈕送出窗體時,
Html.BeginForm
幫助器将導緻窗體張貼到其本身。
運作該應用程式并試着尋找一部電影。
沒有任何
HttpPost
重載的
SearchIndex
方法。你不需要它,因為該方法不更改狀态的應用程式,隻篩選資料。
您可以添加以下
HttpPost SearchIndex
方法。在這種情況下,操作調用程式将比對
HttpPost SearchIndex
方法,并且
HttpPost SearchIndex
方法将運作,如下圖所示。
[HttpPost]
public string SearchIndex(FormCollection fc, string searchString)
{
return "<h3> From [HttpPost]SearchIndex: " + searchString + "</h3>";
}
但是,即使您添加此
HttpPost
版本的
SearchIndex
方法,有這一切如何執行的限制。想象一下你想要添加書簽特定的搜尋或你想要的連結發送給朋友他們可以單擊看看同一篩選清單中的電影。請注意 HTTP POST 請求的 URL 是 GET 請求 (localhost:xxxxx/電影/SearchIndex) 的 URL 相同 — — 在 URL 本身沒有搜尋資訊。現在,搜尋字元串資訊作為窗體字段值發送到伺服器。這意味着您不能捕獲該搜尋資訊以建立書簽或在 URL 中發送給朋友。
解決方案是使用
BeginForm
,它指定 POST 請求應添加到 URL 的搜尋資訊和它應該被路由到公共版本的
SearchIndex
方法的重載。現有無參數
BeginForm
方法替換為以下内容:
@using (Html.BeginForm("SearchIndex","Movies",FormMethod.Get))
現在當您送出一個搜尋,該 URL 包含一個搜尋的查詢字元串。搜尋還會去
HttpGet SearchIndex
操作方法,即使你有
HttpPost SearchIndex
的一種方法。
添加搜尋按流派
如果您添加
HttpPost
版本的
SearchIndex
方法,它現在将其删除。
下一步,您将添加一個功能,讓使用者搜尋電影按類型排列。
SearchIndex
方法替換為以下代碼:
public ActionResult SearchIndex(string movieGenre, string searchString)
{
var GenreLst = new List<string>();
var GenreQry = from d in db.Movies
orderby d.Genre
select d.Genre;
GenreLst.AddRange(GenreQry.Distinct());
ViewBag.movieGenre = new SelectList(GenreLst);
var movies = from m in db.Movies
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
if (string.IsNullOrEmpty(movieGenre))
return View(movies);
else
{
return View(movies.Where(x => x.Genre == movieGenre));
}
}
此版本的
SearchIndex
方法需要一個額外的參數,即
movieGenre
。第一次幾行代碼建立一個
List
對象來儲存電影流派從資料庫。
下面的代碼是從資料庫中檢索所有流派的 LINQ 查詢。
var GenreQry = from d in db.Movies
orderby d.Genre
select d.Genre;
該代碼使用泛型
List
集合的
AddRange
方法向清單中添加所有不同的流派。(不帶
Distinct
修飾符,會添加重複流派 — — 例如,會在我們的示例中兩次添加喜劇)。該代碼然後
ViewBag
對象中存儲的流派的清單。
下面的代碼示範如何檢查
movieGenre
參數。如果它不是空的代碼進一步限制電影查詢,以限制到指定的體裁選看電影。
if (string.IsNullOrEmpty(movieGenre))
return View(movies);
else
{
return View(movies.Where(x => x.Genre == movieGenre));
}
将标記添加到 SearchIndex 視圖,支援按類型排列的主題搜尋
添加到Views\Movies\SearchIndex.cshtml檔案中,隻是之前在
TextBox
傭工
Html.DropDownList
幫助器。已完成的标記如下所示:
<p>
@Html.ActionLink("Create New", "Create")
@using (Html.BeginForm("SearchIndex","Movies",FormMethod.Get)){
<p>Genre: @Html.DropDownList("movieGenre", "All")
Title: @Html.TextBox("SearchString")
<input type="submit" value="Filter" /></p>
}
</p>
運作該應用程式并浏覽到/Movies/SearchIndex。按流派、 按電影名稱,和由這兩個條件,請嘗試搜尋。
在這一節中您審查的 CRUD 操作方法和架構所生成的視圖。您建立了一個搜尋操作方法和視圖,讓使用者搜尋的電影标題和流派。在下一節中,你就會看看如何将一個屬性添加到
Movie
模型以及如何添加一個初始值設定項,将自動建立一個測試資料庫。
==============================翻譯==============================
修改後的
SearchIndex
方法将如下所示:
public ActionResult SearchIndex(string id)
{
string searchString = id;
var movies = from m in db.Movies
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
return View(movies);
}
這裡是不是覺得很奇怪了,就隻改了黃色背景的那倆行
效果如下以前使用者需輸入
http://..../movies/searchIndex/searchString="ghost"
現在隻需要輸入
http://..../movies/searchIndex/ghost
這就是MVC的約定大于配置
這東西文字說明真難組織...
能看懂明白就好,哥寫不出來了...
但是,即使您添加此
HttpPost
版本的
SearchIndex
方法,有這一切如何執行的限制。想象一下你想要添加書簽特定的搜尋或你想要的連結發送給朋友他們可以單擊看看同一篩選清單中的電影。請注意 HTTP POST 請求的 URL 是 GET 請求 (localhost:xxxxx/電影/SearchIndex) 的 URL 相同 — — 在 URL 本身沒有搜尋資訊。現在,搜尋字元串資訊作為窗體字段值發送到伺服器。這意味着您不能捕獲該搜尋資訊以建立書簽或在 URL 中發送給朋友。
解決方案是使用
BeginForm
,它指定 POST 請求應添加到 URL 的搜尋資訊和它應該被路由到公共版本的
SearchIndex
方法的重載。現有無參數
BeginForm
方法替換為以下内容:
這段大緻說的是一個post方法基于get方法查詢的基礎上