6.1 顯示追加信息時所用表單
首先,我們需要在我們的MoviesController類中追加一個Create方法,該方法返回一個視圖,該視圖中包含了用戶輸入信息時所要用到的表單。
- public ActionResult Create()
- {
- return View();
- }
現在讓我們來實現這個Create方法中所要返回的視圖,我們將在這個視圖中向用戶顯示追加數據時所需要用到的表單。在Create方法中點擊鼠標右鍵,並點擊上下文菜單中的“添加視圖”。
在“添加視圖”對話框中選擇“創建強類型視圖”,將模型類指定爲“Movie”,在支架模板中選擇Create,如圖6-1所示。
圖6-1 添加追加數據時所用視圖
點擊添加按鈕,Views文件夾下的Movies文件夾中將會自動添加一個名爲“Create.cshtml”的視圖模板文件。因爲你在支架模板中選擇了“Create”,所以支架模板會在該視圖模板文件中自動生成一些默認代碼。打開該文件進行查看,在該文件中已經自動創建了一個HTML表單,以及一段用來顯示校驗時錯誤信息的文字。Visual Web Developer檢查Movies類,並自動創建與該類中每個屬性相對應的<label>元素以及<input>元素。支架模板自動生成的創建數據所用視圖中的代碼如代碼清單6-1所示。
代碼清單6-1 支架模板自動生成的創建數據所用視圖中的代碼
- @model MvcMovie.Models.Movie
- @{
- ViewBag.Title = "Create";
- }
- <h2>Create</h2>
- <script src="@Url.Content("~/Scripts/jquery.validate.min.js")"
- type="text/javascript"></script>
- <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")"
- type="text/javascript"></script>
- @using (Html.BeginForm()) {
- @Html.ValidationSummary(true)
- <fieldset>
- <legend>Movie</legend>
- <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="Create" />
- </p>
- </fieldset>
- }
- <div>
- @Html.ActionLink("Back to List", "Index")
- </div>
這段代碼中使用了幾個HTML幫助器的方法來幫助簡化HTML標籤的書寫方法。Html.LabelFor幫助器用於顯示字段名(”Title”,”ReleaseDate”,”Genre”或者”Price”)。Html.EditorFor幫助器用於顯示一個提供給用戶輸入信息的HTML的<input>元素。Html.ValidationMessageFor幫助器用於顯示一個針對屬性的校驗信息。請注意我們的視圖模板的頂部有一個“@model MvcMovie.Models.Movie”的聲明,該聲明將我們的視圖模板中的“模型”強類型化成一個Movie類。
運行應用程序,在瀏覽器中輸入“http://localhost:xx/Movies/Create”,瀏覽器中顯示如圖6-2所示。
圖6-2 支架模板自動生成的視圖
在書寫中文網站或中文Web應用程序的時候,可以將代碼清單6-1中的代碼修改爲代碼清單6-2中所示代碼。
代碼清單6-2 將支架模板自動生成的代碼進行漢化
- @model MvcMovie.Models.Movie
- @{
- ViewBag.Title = "追加電影信息";
- }
- <h2>追加電影信息</h2>
- <script src="@Url.Content("~/Scripts/jquery.validate.min.js")"
- type="text/javascript"></script>
- <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")"
- type="text/javascript"></script>
- @using (Html.BeginForm()) {
- @Html.ValidationSummary(true)
- <fieldset>
- <legend>電影</legend>
- <div class="editor-label">
- 標題
- </div>
- <div class="editor-field">
- @Html.EditorFor(model => model.Title)
- @Html.ValidationMessageFor(model => model.Title)
- </div>
- <div class="editor-label">
- 發行日期
- </div>
- <div class="editor-field">
- @Html.EditorFor(model => model.ReleaseDate)
- @Html.ValidationMessageFor(model => model.ReleaseDate)
- </div>
- <div class="editor-label">
- 種類
- </div>
- <div class="editor-field">
- @Html.EditorFor(model => model.Genre)
- @Html.ValidationMessageFor(model => model.Genre)
- </div>
- <div class="editor-label">
- 票價
- </div>
- <div class="editor-field">
- @Html.EditorFor(model => model.Price)
- @Html.ValidationMessageFor(model => model.Price)
- </div>
- <p>
- <input type="submit" value="追加" />
- </p>
- </fieldset>
- }
- <div>
- @Html.ActionLink("返回電影列表", "Index")
- </div>
修改完畢後重新運行程序,然後訪問“http://localhost:xx/Movies/Create”這個地址,瀏覽器中顯示如圖6-3所示。
圖6-3 中文化後的追加電影信息畫面
鼠標右擊瀏覽器中顯示的該頁面,點擊“顯示源代碼”,顯示出來的源代碼如代碼清單6-3所示。(爲了突出本節內容,只顯示與本節中相關部分)。
代碼清單6-3 追加電影信息畫面在瀏覽器中的HTML代碼
- <!DOCTYPE html>
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
- <title>追加電影信息</title>
- <link href="/Content/Site.css" rel="stylesheet" type="text/css" />
- <script src="/Scripts/jquery- 1.4.4.min.js"
- type="text/javascript"></script>
- </head>
- <body>
- <h2>追加電影信息</h2>
- <script src="/Scripts/jquery.validate.min.js"
- type="text/javascript"></script>
- <script src="/Scripts/jquery.validate.unobtrusive.min.js"
- type="text/javascript"></script>
- <form action="/Movies/Create" method="post">
- <fieldset>
- <legend>電影</legend>
- <div class="editor-label">
- 標題
- </div>
- <div class="editor-field">
- <input class="text-box single-line" id="Title" name="Title"
- type="text" value="" />
- <span class="field-validation-valid" data-valmsg-for="Title"
- data-valmsg-replace="true"></span>
- </div>
- <div class="editor-label">
- 發行日期
- </div>
- <div class="editor-field">
- <input class="text-box single-line" data-val="true"
- data-val-required="The ReleaseDate field is required."
- id="ReleaseDate" name="ReleaseDate" type="text" value="" />
- <span class="field-validation-valid"
- data-valmsg-for="ReleaseDate"
- data-valmsg-replace="true">
- </span>
- </div>
- <div class="editor-label">
- 種類
- </div>
- <div class="editor-field">
- <input class="text-box single-line" id="Genre" name="Genre"
- type="text" value="" />
- <span class="field-validation-valid" data-valmsg-for="Genre"
- data-valmsg-replace="true"/>
- </div>
- <div class="editor-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="" />
- <span class="field-validation-valid" data-valmsg-for="Price"
- data-valmsg-replace="true"></span>
- </div>
- <p>
- <input type="submit" value="追加" />
- </p>
- </fieldset>
- </form>
- <div>
- <a href="/Movies">返回電影列表</a>
- </div>
- <div id="footer">
- </div>
- </body>
- </html>
從這段代碼中可以看出,表單的action屬性被設置爲“/Movies/Create”,當點擊追加按鈕時會把表單中各文本框中的數據提交到服務器端進行保存。
6.2 處理HTTP-POST
到此爲止,我們已經實現了顯示追加數據所用表單的所需代碼。我們的下一步是編寫代碼來進行表單提交到服務器後的處理。我們將要獲取用戶在數據庫中輸入的信息並且將它們作爲一個新的Movie保存到數據庫中。
爲了實現這一處理,我們需要在MoviesController類中追加第二個Create方法。這個Create方法具有一個[HttpPost]屬性,它意味着我們將要用它來處理提交到“/Movies/Create”這個URL地址的請求。另外,所有提交到“/Movies/Create”這個URL地址的非POST的請求(即GET請求)將被第一個Create方法進行處理,即簡單地返回一個空的表單。
代碼清單6-4中所示代碼爲MoviesController類中的兩個Create方法的全部代碼。
代碼清單6-4 MoviesController類中的兩個Create方法的全部代碼
- public ActionResult Create()
- {
- return View();
- }
- [HttpPost]
- public ActionResult Create(Movie newMovie)
- {
- if (ModelState.IsValid)
- {
- db.Movies.Add(newMovie);
- db.SaveChanges();
- return RedirectToAction("Index");
- }
- else
- return View(newMovie);
- }
之前我們介紹了ASP.NET MVC可以自動地將一個URL地址中的查詢字符串中的參數(例如:傳遞到“/HelloWorld/Welcome?name=Scott&numTimes=5”)作爲一個方法的參數傳遞到方法中。同樣地,除了傳遞查詢字符串中的參數之外,ASP.NET MVC也可以用這種方法來傳遞提交後的表單參數。
提交後的表單參數可以作爲一個獨立的參數傳遞到一個方法中。例如,ASP.NET MVC framework可以將我們提交的表單中的控件值作爲參數傳遞到具有HttpPost屬性的Create方法中,如下所示。
- [HttpPost]
- public ActionResult Create(string title, DateTime releaseDate, string genre,
- decimal price)
- {}
提交的表單值也可以被映射到一個複合的,具有屬性的對象(譬如我們的Movie類),並且作爲一個單一的參數傳遞到一個方法中。在代碼清單6-4中我們使用的就是這個方法。請注意Create方法是怎樣作爲一個參數來接收Movie對象的。
- [HttpPost]
- public ActionResult Create(Movie newMovie)
- {
- if (ModelState.IsValid)
- {
- db.Movies.Add(newMovie);
- db.SaveChanges();
- return RedirectToAction("Index");
- }
- else
- return View(newMovie);
- }
ModelState.IsValid屬性用來檢查提交的表單中的數據是否能夠被用來創建一個Movie對象。如果數據是有效的,我們的代碼將把提交上來的這個Movie類追加在MoviesDBContext對象的實例中的Movies集合中。調用我們的MoviesDBContext對象實例的SaveChanges方法將把這個Movie對象保存在數據庫中。保存數據完畢後,代碼把畫面重定向到MoviesController類的Index方法中,瀏覽器中將會打開電影清單顯示畫面,並且在電影清單中顯示剛纔追加的這條數據。
如果提交的值是無效的,將會返回到電影信息追加畫面中,並且在表單的各輸入控件中顯示各自的提交的值。各輸入控件的Html.ValidationMessageFor幫助器將會顯示對應的出錯信息。
6.3 追加一條電影信息
運行應用程序,在瀏覽器中輸入“http://localhost:xx/Movies/Create”,在表單中輸入一條電影信息,然後點擊追加按鈕,如圖6-4所示。
圖6-4 追加電影信息
點擊追加按鈕進行提交,表單中輸入的這條電影信息將會保存到數據庫中,保存後瀏覽器中將打開電影清單畫面,並且將這條追加的電影顯示在清單中,如圖6-5所示。
圖6-5 追加後電影將顯示在電影清單中
你可能已經注意到了在這個電影清單畫面中將剛纔追加的電影票價顯示成了10元,而不是用戶輸入的9.99元,這是因爲當前該數據表中Decimal類型的默認精度只能識別與處理整數值,並且自動將小數部分四捨五入。關於如何解決這個問題,我們將在下一節中對模型進行一些調整的時候會同時進行介紹。
現在我們已經有了一個Web應用程序的雛形,我們可以在數據庫中追加數據,顯示數據。代碼清單6-5是現在這個MoviesController類的完整代碼。
代碼清單6-5 MoviesController類的完整代碼
- using MvcMovie.Models;
- using System.Linq;
- using System;
- using System.Web.Mvc;
- namespace MvcMovie.Controllers
- {
- public class MoviesController : Controller
- {
- MovieDBContext db = new MovieDBContext();
- public ActionResult Index()
- {
- var movies=from m in db.Movies
- where m.ReleaseDate>new DateTime(1984,6,1)
- select m;
- return View(movies.ToList());
- }
- public ActionResult Create()
- {
- return View();
- }
- [HttpPost]
- public ActionResult Create(Movie newMovie)
- {
- if (ModelState.IsValid)
- {
- db.Movies.Add(newMovie);
- db.SaveChanges();
- return RedirectToAction("Index");
- }
- else
- return View(newMovie);
- }
- }
- }