在本節中將會給Movie模型添加驗證邏輯。並且確保這些驗證規則在用戶創建或編輯電影時被執行。
拒絕重復 DRY ASP.NET MVC 的核心設計信條之一是DRY: "不要重復自己(DRY --Don’t Repeat Yourself)"。ASP.NET MVC鼓勵您指定功能或者行為,只做一次,然後將它應用到應用程序的各個地方。這可以減少您需要編寫的代碼量,並減少代碼出錯率,易於代碼維護。 給ASP.NET MVC 和 Entity Framework Code First 提供驗證支持是 DRY 信條的一次偉大實踐。您可以在一個地方 (模型類) 中以聲明的方式指定驗證規則,這個規則會在應用程序中的任何地方執行。 讓我們看看您如何在本電影應用程序中,使用此驗證支持。 給電影模型添加驗證規則 您將首先向Movie類添加一些驗證邏輯。 打開Movie.cs 文件,注意到System.Web 命名空間並未包含System.ComponentModel.DataAnnotations. DataAnnotations提供了一組內置的嚴重屬性,可供您應用於類、屬性。(DataAnnotations也包含一個DataType屬性,來幫助格式化的辦法來校驗) 更新Movie類,以利用內置的Required、 StringLength, RegularExpression和Range驗證屬性。以下面的代碼為例,以應用驗證屬性。 復制代碼 public class Movie { public int ID { get; set; } [StringLength(60, MinimumLength = 3)] public string Title { get; set; } [Display(Name = "Release Date")] [DataType(DataType.Date)] [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)] public DateTime ReleaseDate { get; set; } [RegularExpression(@"^[A-Z]+[a-zA-Z''-'s]*$")] [Required] [StringLength(30)] public string Genre { get; set; } [Range(1, 100)] [DataType(DataType.Currency)] public decimal Price { get; set; } [RegularExpression(@"^[A-Z]+[a-zA-Z''-'s]*$")] [StringLength(5)] public string Rating { get; set; } } 復制代碼 在StringLength屬性設置字符串的最大長度,它會在數據庫上設置此限制,因此的數據庫schema將發生變化。右鍵單擊電影表, 在服務器資源管理器(Server explorer),然後單擊打開表定義(Open Table Definition): clip_image002 在上面的圖片中,你可以看到所有的字符串字段被設置為了NVARCHAR (MAX)數據類型. 我們將使用遷移來更新架構。生成解決方案,然後打開軟件包管理器控制台(the Package Manager Console ),輸入如下命令: add-migration DataAnnotations update-database 當這個命令完成後,Visual Studio將打開類代碼文件,它定義了新DbMIgration派生類(DataAnnotations),你可以在Up方法看到更新架構約束代碼如下所示: 復制代碼 public override void Up() { AlterColumn("dbo.Movies", "Title", c => c.String(maxLength: 60)); AlterColumn("dbo.Movies", "Genre", c => c.String(nullable: false, maxLength: 30)); AlterColumn("dbo.Movies", "Rating", c => c.String(maxLength: 5)); } 復制代碼 該流派(Genre)字段不再可為Null(也就是說,你必須輸入一個值)。該評級(Rating)字段最大長度為5, 標題的最大長度為60。標題(Title )和價格 (Price)的范圍的最小長度並沒有更改。 請在數據庫中,檢查電影表的schema: clip_image004 該字符串字段顯示新的長度限制和流派字段(Genre)不能再為空。 驗證屬性指明您想要應用到模型屬性的行為。Required 和MinimumLength屬性指出某一屬性不可為空,但沒有什麼能夠阻止用戶輸入空格來驗證。該RegularExpression屬性是用來限制哪些字符可以輸入。在上面的代碼中,流派(Genre)和等級(Rating)只能使用字母(空格,數字和特殊字符是不允許的)。該范圍(Range )屬性約束的值在一個指定范圍內。在StringLength 屬性允許您設置一個字符串屬性的最大長度,以及最小長度(可選的)。值類型(decimal, int, float, DateTime)有固有必需設置的,不需要的Required屬性。 Code First確保你的模型在指定class上在驗證規則強制執行之前應用程序將變更儲存在數據庫中。例如,下面的代碼將拋出一個DbEntityValidationException 異常時,調用SaveChanges方法時,因為幾個必要的Movie屬性缺少: 復制代碼 MovieDBContext db = new MovieDBContext(); Movie movie = new Movie(); movie.Title = "Gone with the Wind"; db.Movies.Add(movie); db.SaveChanges(); // <= Will throw server side validation exception 復制代碼 上面的代碼會拋出以下異常: Validation failed for one or more entities. 參閱 'EntityValidationErrors' 屬性獲得更多信息. 具有通過.NET Framework會自動強制執行的驗證規則, 有助於使你的應用程序更加健壯。它還確保可以不會忘記驗證的東西,即在不經意間不會讓壞的數據寫入數據庫。 ASP.NET MVC 的驗證錯誤UI 重新運行應用程序,浏覽 /Movies的 URL。 單擊Create New鏈接,來添加一部新電影。在窗體中填寫一些無效值,然後單擊Create按鈕。 如同jQuery的客戶端驗證來檢測到錯誤時,它會顯示一個錯誤消息。 注意,為了使jQuery支持使用逗號的非英語區域的驗證 ,需要設置逗號(",")來表示小數點,如本教程前面所述, 你須引入NuGet globalize。請注意,表單在每一個相應的驗證錯誤消息旁邊,已經自動使用紅色邊框的顏色突出顯示文本框指明無效數據。這些錯誤是強制執行了客戶端端(使用JavaScript和jQuery)和服務器端(如果用戶禁用了JavaScript)。 一個真正的好處是,你並不需要更改MoviesController類或Create.cshtml視圖中的一行代碼,來啟用此驗證的用戶界面。您在前面教程所創建的控制器和視圖會自動啟用,使用驗證指明的Movie model類的屬性。使用Edit行為方法,同樣的驗證方法也完全適用。直到沒有任何客戶端驗證錯誤的表單數據,才會被發送回服務器。您可以通過在HTTP POST方法,用一個斷點來驗證這一點; 或通過使用fiddler tool,或者IE浏覽器F12 developer tools。 如何驗證創建視圖和創建方法 您可能很想知道驗證用戶界面在沒有更新控制器或視圖代碼的情況下是如何生成的。下面列出了MovieController類中的Create方法。它們是之前教程中自動生成的,並沒有修改。 復制代碼 public ActionResult Create() { return View(); } // POST: /Movies/Create // To protect from overposting attacks, please enable the specific properties you want to bind to, for // more details see http://go.microsoft.com/fwlink/?LinkId=317598. [HttpPost] [ValidateAntiForgeryToken] public ActionResult Create([Bind(Include = "ID,Title,ReleaseDate,Genre,Price,Rating")] Movie movie) { if (ModelState.IsValid) { db.Movies.Add(movie); db.SaveChanges(); return RedirectToAction("Index"); } return View(movie); } 復制代碼 第一種(HTTP GET)Create 方法用來顯示初始的創建form。第二個 ([HttpPost]) 方法處理form的請求。第二種Create方法 (HttpPost 版本) 調用 ModelState.IsValid來檢查是否有任何的Movie驗證錯誤。調用此方法將驗證對象上所有應用了驗證約束的屬性。如果對象含有驗證錯誤,則Create方法會重新顯示初始的form。如果沒有任何錯誤,方法將保存信息到數據庫。在我們的電影示例中,我們使用了驗證,當客戶端檢測到錯誤時,form不會被post到服務器;所以第二個Create方法永遠不會被調用。如果您在浏覽器中禁用了 JavaScript,客戶端驗證也會被禁用,HTTP POST Create方法會調用 ModelState.IsValid來檢查影片是否含有任何驗證錯誤。 您可以在HttpPost Create方法中設置一個斷點,當客戶端驗證檢測到錯誤時,不會post form數據,所以永遠不會調用該方法。如果您在浏覽器中禁用 JavaScript,然後提交具有錯誤信息的form,斷點將會命中。您仍然得到充分的驗證,即使在沒有 JavaScript的情況下。 下圖顯示了如何禁用 Internet Explorer 中的 JavaScript。 clip_image008 clip_image010 下圖顯示了如何在火狐浏覽器中禁用 JavaScript。 clip_image012 下圖顯示了如何在 Chrome 浏覽器中禁用 JavaScript。 clip_image014 下面是框架代碼在之前的教程中生成的Create.cshtml視圖模板。它用來為以上兩個操作方法來顯示初始的form,同時在驗證出錯時來重新顯示視圖。 復制代碼 @model MvcMovie.Models.Movie @{ ViewBag.Title = "Create"; } <h2>Create</h2> @using (Html.BeginForm()) { @Html.A