在這本部分會將驗證邏輯添加到Movie
模式,和你會確保驗證規則執行任什麼時候候用戶試圖建立或編輯使用該應用程序的一部電影。html
ASP.NET MVC 的核心設計信條之一是 DRY(」Don't Repeat Yourself「,不要重複)。ASP.NET MVC 鼓勵你只有一次,指定的功能或行爲,而後讓它無處不在應用程序中反映。這減小了須要編寫的代碼量,並使你寫更少錯誤傾向和易於維護的代碼。jquery
ASP.NET MVC 和 Entity Framework Code First 中提供的驗證支持就是操做中 DRY 原則的很好的例子。您能夠在一個地方 (在模型類) 中以聲明方式指定驗證規則和無處不在應用程序中強制執行的規則。git
讓咱們看看如何您能夠利用這種驗證支持的在電影中的應用。github
你就開始向Movie
類添加一些驗證邏輯。web
打開Movie.cs文件。 System.ComponentModel.DataAnnotations
命名空間引用的文件的頂部添加using
語句:ajax
using System.ComponentModel.DataAnnotations;
注意到該命名空間不包含System.Web
。DataAnnotations 提供了一組內置的驗證特性,您能夠以聲明方式適用於任何類或屬性。正則表達式
如今更新Movie
課可以利用內置的Required
, StringLength
和Range
驗證屬性。使用下面的代碼爲例,應用屬性的位置。chrome
public class Movie { public int ID { get; set; } [Required] public string Title { get; set; } [DataType(DataType.Date)] public DateTime ReleaseDate { get; set; } [Required] public string Genre { get; set; } [Range(1, 100)] [DataType(DataType.Currency)] public decimal Price { get; set; } [StringLength(5)] public string Rating { get; set; } }
運行該應用程序,你又會獲得下面的運行的時錯誤:數據庫
咱們將咱們的遷移,以更新 scheam。生成解決方案,而後打開程序包管理器控制檯窗口並輸入如下命令:express
add-migration AddDataAnnotationsMig
update-database
當此命令完成,Visual Studio 打開定義具備指定的名稱 (AddDataAnnotationsMig),新的DbMIgration
派生類的類文件並在Up
的方法,你能夠看到的代碼更新架構約束。Title
和Genre
領域再也不是能夠爲 null (也就是說,您必須輸入一個值) 和Rating
字段的最大長度爲 5。
驗證屬性指定您想要在將它們應用於模型屬性上實施的行爲。 Required
的屬性指示的屬性必須具備一個值 ;在此示例中,一部電影都必須有Title
、 ReleaseDate
、Genre
和Price
屬性值纔有效。Range
屬性限制對指定範圍內的值。StringLength
屬性容許您設置一個字符串屬性的最大長度和 (可選) 其最小長度。內部類型 (例如decimal, int, float, DateTime
) 默認須要和不須要的Required
屬性。
代碼首先確保您在一個模型類指定的驗證規則執行以前應用程序將更改保存在數據庫中。例如,下面的代碼在調用SaveChanges
方法時,將引起異常,由於幾個須要Movie
屬性的值是失蹤和價格是零 (即超出有效範圍)。
MovieDBContext db = new MovieDBContext(); Movie movie = new Movie(); movie.Title = "Gone with the Wind"; movie.Price = 0.0M; db.Movies.Add(movie); db.SaveChanges();// <= Will throw server side validation exception
具備驗證規則會自動執行由.NET 框架有助於使您的應用程序更加健壯。它還確保你不能忘驗證的東西,無心中讓壞的數據到數據庫中。
下面是完整的代碼清單的更新的Movie.cs文件:
using System; using System.Data.Entity; using System.ComponentModel.DataAnnotations; namespace MvcMovie.Models { public class Movie { public int ID { get; set; } [Required] public string Title { get; set; } [DataType(DataType.Date)] public DateTime ReleaseDate { get; set; } [Required] public string Genre { get; set; } [Range(1, 100)] [DataType(DataType.Currency)] public decimal Price { get; set; } [StringLength(5)] public string Rating { get; set; } } public class MovieDBContext : DbContext { public DbSet<Movie> Movies { get; set; } } }
從新運行應用程序,而後定位到/Movies URL。
單擊建立新的連接以添加一部新電影。填寫一些無效的值,而後單擊建立按鈕。
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> }
請注意如何窗體已自動用於紅色邊框的顏色突出顯示文本框中包含無效數據,已經發出在每個適當的驗證錯誤消息。錯誤強制執行 (使用 JavaScript 和 jQuery) 的客戶端和服務器端 (以防用戶已禁用 JavaScript)。
真正的好處是你不須要爲了使這種驗證 UI 更改一行代碼在MoviesController
類中或在Create.cshtml視圖中。控制器和視圖建立早些時候在本教程中,自動撿起你經過使用驗證特性上Movie
模式類的屬性指定的驗證規則。
你可能已經注意到的屬性Title
和Genre
,所需的屬性是不強制執行直到你提交表單 (擊中了建立按鈕),或在輸入字段中輸入文本並刪除它。字段是最初爲空 (例如建立視圖字段) 並具備惟一必需的屬性並無其餘的驗證屬性,您能夠執行如下操做來觸發驗證:
上面的順序將沒有擊中提交按鈕觸發必需的驗證。簡單地擊打而無需輸入任何字段的提交按鈕,將會觸發客戶端驗證。有沒有客戶端驗證錯誤以前表單數據不會發送到服務器。您能夠測試這一個破發點置於 HTTP Post 方法或用提琴手工具或 IE 9 F12 開發人員工具.
您可能想知道如何驗證用戶界面生成沒有任何更新的控制器或視圖中的代碼。下一個清單顯示MovieController
類中的方法 Create
的外觀。他們從早些時候在本教程中建立的方式不變。
// // GET: /Movies/Create public ActionResult Create() { return View(); } // // POST: /Movies/Create [HttpPost] public ActionResult Create(Movie movie) { if (ModelState.IsValid) { db.Movies.Add(movie); db.SaveChanges(); return RedirectToAction("Index"); } return View(movie); }
第一次 (HTTP GET)Create
操做方法顯示初始建立窗體。第二個 ([HttpPost]
) 版本處理窗體發佈。第二種Create
方法 ( HttpPost
版本) 調用 ModelState.IsValid
來檢查電影有否任何驗證錯誤。調用此方法的計算結果已應用於該對象的任何驗證屬性。若是對象具備驗證錯誤,則Create
方法從新顯示窗體。若是沒有錯誤,該方法在數據庫中保存的新電影。在咱們電影的例子,咱們使用的,檢測到 ; 客戶端上的驗證錯誤時不向服務器發送窗體第二Create
永遠不會調用方法。若是您在您的瀏覽器中禁用 JavaScript,禁用客戶端驗證和Create
HTTP POST 方法調用ModelState.IsValid
來檢查電影有否任何驗證錯誤。
您能夠在HttpPost Create
方法中設置一個斷點,並驗證永遠不會調用該方法,客戶端驗證不會提交表單數據時檢測到驗證錯誤。若是您在您的瀏覽器中禁用 JavaScript,而後提交具備錯誤的窗體,將命中破發點。你仍然獲得了充分驗證沒有 JavaScript。下面的圖像演示如何禁用 JavaScript 在 Internet explorer 中。
下面的圖像演示如何在火狐瀏覽器中禁用 JavaScript。
下面的圖像演示如何禁用 JavaScript 的 Chrome 瀏覽器。
下面是您搭建早些時候在本教程中的Create.cshtml視圖模板。如上所示兩個操做方法使用顯示初始窗體,並在出現錯誤時從新顯示它。
@model MvcMovie.Models.Movie
@{
ViewBag.Title = "Create";
}
<h2>Create</h2> <script src="@Url.Content("~/Scripts/jquery.validate.min.js")"></script> <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")"></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> <div class="editor-label"> @Html.LabelFor(model => model.Rating) </div> <div class="editor-field"> @Html.EditorFor(model => model.Rating) @Html.ValidationMessageFor(model => model.Rating) </div> <p> <input type="submit" value="Create" /> </p> </fieldset> } <div> @Html.ActionLink("Back to List", "Index") </div>
請注意代碼如何使用Html.EditorFor
幫助器輸出的每一個Movie
屬性的<input>
元素。此幫助器旁邊是對Html.ValidationMessageFor
幫助器方法的調用。這兩個幫助器方法處理由控制器傳遞到視圖 (在本例中,是一個Movie
對象) 的模型對象。他們會自動查找指定的模型和顯示的錯誤消息,做爲適當的驗證屬性。
關於這種方法真的很好的是控制器既建立視圖模板知道任何有關實施的實際驗證規則或顯示的特定錯誤消息。在Movie
類僅指定了驗證規則和錯誤字符串。這些相同的驗證規則將自動應用到編輯視圖和任何其餘視圖模板能夠建立,編輯您的模型。
若是你想要在之後更改的驗證邏輯,你能夠在一個地方經過將驗證屬性添加到模型 (在此示例中,movie
課)。你沒必要擔憂不符合規則 》 如何強制執行的應用程序的不一樣部分 — — 全部的驗證邏輯會在一個地方定義和使用無處不在。這使代碼很乾淨,並使它易於維護和發展。它意味着你會充分尊重 DRY 原則。
打開Movie.cs文件並檢查Movie
課。 System.ComponentModel.DataAnnotations
命名空間提供了內置的驗證特性集的格式屬性。咱們已應用一個DataType
的枚舉值的發佈日期和價格字段。下面的代碼演示的ReleaseDate
和Price
屬性與相應的DisplayFormat
屬性。
[DataType(DataType.Date)] public DateTime ReleaseDate { get; set; } [DataType(DataType.Currency)] public decimal Price { get; set; }
DataType
屬性不是驗證特性,它們被用來告訴視圖引擎如何呈現的 HTML。在上面的示例中, DataType.Date
屬性顯示電影日期做爲僅限於日期沒有時間。例如,下面的DataType
屬性不須要驗證的數據的格式:
[DataType(DataType.EmailAddress)] [DataType(DataType.PhoneNumber)] [DataType(DataType.Url)]
上面列出的屬性僅提供視圖引擎來設置數據的格式的提示 (如提供屬性和 < > url 的和 < href="mailto:EmailAddress.com"> 電子郵件。可使用正則表達式屬性來驗證數據的格式。
使用DataType
屬性的替代方法,您能夠顯式設置一個DataFormatString
值。下面的代碼演示了具備一個日期格式字符串的釋放日期屬性 (namely,"d")。你會使用這指定做爲一部分的發行日期時間不要。
[DisplayFormat(DataFormatString = "{0:d}")] public DateTime ReleaseDate { get; set; }
下面的代碼格式設置爲貨幣的Price
屬性。
[DisplayFormat(DataFormatString = "{0:c}")] public decimal Price { get; set; }
完整的Movie
類以下所示。
public class Movie { public int ID { get; set; } [Required] public string Title { get; set; } [DataType(DataType.Date)] public DateTime ReleaseDate { get; set; } [Required] public string Genre { get; set; } [Range(1, 100)] [DataType(DataType.Currency)] public decimal Price { get; set; } [StringLength(5)] public string Rating { get; set; } }
運行該應用程序,而後瀏覽到Movies
控制器。很好地格式化的發佈日期和價格。下面的圖像顯示的發佈日期和價格使用"FR-FR"做爲文化。
下面的圖像顯示了相同的數據,顯示與默認區域性 (美國英語)。
在本系列的下一部分,咱們會反省中應用,做了一些改進的自動生成的Details
和 Delete
方法。