ASP.NET MVC 5 學習教程:添加驗證


起飛網 ASP.NET MVC 5 學習教程目錄:

在本節中,我們將為Movie模型添加驗證邏輯,並確認驗證規則在用戶試圖使用程序創建和編輯電影時有效。

DRY 原則

ASP.NET MVC 的一個核心原則是DRY(Don't Repeat Yourself - 不做重復的事情)。ASP.NET MVC 鼓勵你一次性的指定功能或行為,然后應用程序的其它地方通過映射得到它,這樣一來就減少了大量的代碼,從而減少了出錯誤的可能性,並且更易於維護。

ASP.NET  MVC  和 Entity Framework Code First 提供的驗證能是 DRY 原則的不錯的實踐。你可以在一處(在模型類中)定義驗證規則,從而在應用程序中的所有地方都可以使用這個規則。

接下來讓我們看看如何在現在的Movie 中添加高級的驗證規則吧。

為模型添加驗證規則

現在我們開始為Movie類添加一些驗證規則。

打開文件 Movie.cs,注意命名空間 System.ComponentModel.DataAnnotations 並不包含 System.Web。DataAnnotations 提供了內置的驗證特性,你可以將它們用在任何類或屬性中(它還包含了像DataType這樣的格式化的特性,它們不參與任何驗證)。

為Movie類添加一些內置的驗證規則,修改后的代碼如下:

代碼清單1:添加了驗證規則的Movie類

public class Movie
{
    public int ID { get; set; }

    [Required]
    [StringLength(60, MinimumLength = 3)]
    public string Title { get; set; }

    [Display(Name = "Release Date")]
    [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)]
    [Required]
    public string Rating { get; set; }
}

使用數據遷移來更新數據庫結構。編譯解決方案,然后打開“程序包管理器控制台”窗口,執行下面的命令:

add-migration DataAnnotations
update-database

當這兩個命令執行完成之后,Visual Studio 為我們創建了 DataAnnotations 類,它繼承自 DbMigration。打開文件,在它的Up方法中,你會看到升級結構的代碼:

代碼清單2:升級數據庫結構的Up方法

public override void Up()
{
    AlterColumn("dbo.Movies", "Title", c => c.String(nullable: false, maxLength: 60));
    AlterColumn("dbo.Movies", "Genre", c => c.String(nullable: false));
    AlterColumn("dbo.Movies", "Rating", c => c.String(nullable: false, maxLength: 5));
}

從代碼中可以看出,Title、Genre和Rating三個字段不再允許為空(這意味着你必須輸入一個值)。Rating 字段的最大長度為5,Title 的最大長度為60,最小長度為3。

Code First 確保在保存到數據庫的時候使用你指定的規則對數據進行驗證,例如,下面的代碼在調用SaveChanges的時候會拋出一個錯誤:

MovieDBContext db = new MovieDBContext();

Movie movie = new Movie();
movie.Title = "Gone with the Wind";

db.Movies.Add(movie);  
db.SaveChanges();        // <= 會引發一個服務器段的錯誤,因為movie的必須的字段沒有賦值 

驗證規則在保存的時候自動生效使得程序變得更為健壯,它可以在是你忘記去驗證,而在不經意間阻止不合法的進入數據庫。

ASP.NET MVC 客戶端驗證

運行應用程序,瀏覽地址 /movies,點擊“Create New”鏈接添加一個電影。如果我們在輸入過程中出現一些不合法的數據,客戶端將會顯示一些錯誤,這是通過 jQuery 客戶端驗證來實現的。下面是一些錯誤信息:

圖1:客戶端驗證信息

image

當出現錯誤的時候,文本框會被加上紅色的邊框,並且會顯示一段錯誤描述信息。這些錯誤信息可以在客戶端(使用Javascript 和 jQuery)和服務器(當客戶端Javascript無效時)段生效。

一個真正的好處是,你不需要在MoviesController 或 Create.cshtml 中修改一行代碼來啟用客戶端驗證,控制器和視圖會根據我們之前定義在Movie類中的驗證特性自動選擇驗證規則。

表單數據出現錯誤的時候不會被提交到服務器端。

驗證是如何工作的

你可能會覺得奇怪,客戶端驗證是如何在沒有修改控制器或視圖代碼的情況下生成的。下面的代碼顯示了MovieController的Create方法,它和我們前面的教程中的Create代碼一樣,並沒有經過修改:

代碼清單3:Create 方法

//
// GET: /Movies/Create
public ActionResult Create()
{
    return View();
}

//
// POST: /Movies/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Movie movie)
{
    if (ModelState.IsValid)
    {
        db.Movies.Add(movie);
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    return View(movie);
}

第一個Create方法顯示一個表單,第二個Create方法用來處理POST請求提交的表單數據。第二個Create方法調用ModelState.IsValid來檢查movie數據是否存在驗證錯誤,調用這個方法來檢查驗證規則,如果存在錯誤,Create 方法將會重新顯示這個表單,如果沒有,則會將Movie數據保存到數據庫。在我們的例子中,當驗證出現錯誤的時候表單不會提交到服務器,第二個Create方法將不會調用。如果你禁用了Javascript客戶端驗證,第二個Create方法則會調用ModelState.IsValid對數據進行檢查。

你可以通過在HttpPost Create 方法中添加斷點來監視是否被調用。當客戶端出現錯誤的時候表單將不會提交,如果我們禁用客戶端的Javascript,表單將錯誤的數據提交到服務器,斷點將會跟蹤到。下面我們介紹一下如何在IE和Google瀏覽器中禁用Javascript。

在 IE 中禁用Javascript

打開Internet選項,在安全選項中選中“本地Intranet”,點擊“自定義級別”按鈕:

圖2:自定義安全級別

image

然后在安全設置窗口中,找到“活動腳本”,選擇“禁用”:

圖3:禁用活動腳本

image

點擊“確定”按鈕,然后跟蹤你提交的數據:

圖4:跟蹤到未通過驗證的數據

image

在火狐(FireFox)中禁用Javascript

圖5:在火狐中禁用Javascript

image

在Google Chrome中禁用Javascript

圖6:在Google Chrome 中禁用Javascript

image

下面是 Create.cshtml 視圖的代碼,它被控制器中的Create方法用來顯示初始的form表單,或在發生錯誤時重新顯示帶錯誤信息的表單數據。

代碼清單4:Create.cshtml

@model MvcMovie.Models.Movie

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)

    <fieldset class="form-horizontal">
        <legend>Movie</legend>

        <div class="control-group">
            @Html.LabelFor(model => model.Title, new { @class = "control-label" })
            <div class="controls">
                @Html.EditorFor(model => model.Title)
                @Html.ValidationMessageFor(model => model.Title, null, new { @class = "help-inline" })
            </div>
        </div>

        <div class="control-group">
            @Html.LabelFor(model => model.ReleaseDate, new { @class = "control-label" })
            <div class="controls">
                @Html.EditorFor(model => model.ReleaseDate)
                @Html.ValidationMessageFor(model => model.ReleaseDate, null, new { @class = "help-inline" })
            </div>
        </div>

        <div class="control-group">
            @Html.LabelFor(model => model.Genre, new { @class = "control-label" })
            <div class="controls">
                @Html.EditorFor(model => model.Genre)
                @Html.ValidationMessageFor(model => model.Genre, null, new { @class = "help-inline" })
            </div>
        </div>

        <div class="control-group">
            @Html.LabelFor(model => model.Price, new { @class = "control-label" })
            <div class="controls">
                @Html.EditorFor(model => model.Price)
                @Html.ValidationMessageFor(model => model.Price, null, new { @class = "help-inline" })
            </div>
        </div>

        <div class="control-group">
            @Html.LabelFor(model => model.Rating, new { @class = "control-label" })
            <div class="controls">
                @Html.EditorFor(model => model.Rating)
                @Html.ValidationMessageFor(model => model.Rating, null, new { @class = "help-inline" })
            </div>
        </div>

        <div class="form-actions no-color">
            <input type="submit" value="Create" class="btn" />
        </div>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}

模型格式化輸出

打開文件Movie.cs,檢查Movie類,System.ComponentModel.DataAnnotations 命名空間除了一套內置的驗證特性外,還提供了格式化特性。我們已經在ReleaseDate 和Price字段用到過DataType枚舉,下面的代碼展示了ReleaseDate和Price屬性中使用的DisplayFormat特性:

代碼清單5:使用了DisplayFormat的字段

[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }

[Range(1, 100)]
[DataType(DataType.Currency)]
public decimal Price { get; set; }

DataType特性不是驗證特性,他們用來告訴試圖引擎如何繪制HTML。在上面的例子中,DataType.Date 特性使ReleaseDate顯示的時候只顯示日期部分,而不顯示時間。下面的DataType特性不驗證數據的格式:

[DataType(DataType.EmailAddress)]
[DataType(DataType.PhoneNumber)]
[DataType(DataType.Url)]

這些特性只為試圖引擎格式化顯示數據時提供建議。你可以使用RegularExpression 特性連驗證數據的格式。

除了使用現成的DataType 格式化特性之外,你還可以明確指定 DataFormatString 值。下面的代碼展示了ReleaseDate屬性使用格式化字符串的情況,你可以使用它來不顯示ReleaseDate日期的時間部分:

[DisplayFormat(DataFormatString = "{0:d}")]
public DateTime ReleaseDate { get; set; }

下面的代碼將Price顯示為貨幣的格式:

[DisplayFormat(DataFormatString = "{0:c}")]
public decimal Price { get; set; }

完整的Movie類代碼如下:

代碼清單6:Movie類

public class Movie
{
    public int ID { get; set; }

    [Required]
    [StringLength(60, MinimumLength = 3)]
    public string Title { get; set; }

    [Display(Name = "Release Date")]
    [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)]
    [Required]
    public string Rating { get; set; }
}

下面的代碼展示了如何將特性合並在一行顯示:

代碼清單7:合並特性后的Movie類

public class Movie
{
    public int ID { get; set; }

    [Required, StringLength(60, MinimumLength = 3)]
    public string Title { get; set; }

    [Display(Name = "Release Date"), 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; }

    [Required, StringLength(5)]
    public string Rating { get; set; }
}

在本系列的下一部分,我們將回顧整個應用程序,並對自動生成的Details 和Delete 方法做一些改進。

本文同時發布在起飛網,原文地址:http://www.qeefee.com/mvc/mvc-5-adding-validation


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM