本文章是由機器翻譯。

ASP.NET 有絕招

模型驗證 ASP.NET MVC 2 中的中繼資料 (& I)

K. Scott Allen

下載程式碼範例

加入至 ASP.NET MVC 2 版本的新功能之一是能夠驗證使用者輸入伺服器和用戶端上。 您只需要是提供架構需要驗證的資料有關的資訊並架構會採取謹慎的硬式工作和詳細資料。

此功能是極大 boon 對於那些我們撰寫自訂驗證程式碼,並執行簡單模型驗證 ASP.NET MVC 1.0 自訂模型文件夾。 在這篇文章我查看 ASP.NET MVC 2 中的 [內建驗證] 支援。

我要討論新功能之前不過,我打算重新瀏覽舊的方法。 驗證功能,在 ASP.NET WebForms 中的有提供我服務適用於許多年。 我認為 ’s 檢閱這些了解理想的驗證架構提供很有用。

控制驗證

如果您曾經使用 ASP.NET WebForms,您知道 ’s 相當容易將驗證邏輯加入至一個 WebForm。 您表示使用控制項的驗證規則。 比方說如果想請確定使用者在文字方塊控制項中輸入一些文字您只是將 RequiredFieldValidator 控制項新增指向該文字方塊就像這樣:

<form id="form1" runat="server">
  <asp:TextBox runat="server" ID="_userName" />
  <asp:RequiredFieldValidator runat="server" ControlToValidate="_userName"
                               ErrorMessage="Please enter a username" />
  <asp:Button runat="server" ID="_submit" Text="Submit" />
</form>

RequiredFieldValidator 封裝用戶端和伺服器端邏輯,以確保使用者提供使用者名稱。 為了用戶端驗證控制項會 JavaScript 發出至用戶端 ’s 瀏覽器並這個指令碼可確保使用者能滿足所有驗證規則張貼表單之前回至伺服器。

想想這些 WebForm 驗證控制項提供 — ’re 相當強大!

  • 您可以用來以宣告方式表示單一位置中的一個頁面的驗證規則。
  • 如果使用者 doesn’t 履行驗證規則,用戶端驗證可防止到伺服器往返作業。
  • 伺服器驗證可防止惡意使用者規避用戶端指令碼。
  • 伺服器和用戶端的驗證邏輯保持同步而變得維護問題。

但是您 can’t ASP.NET MVC 中使用這些驗證控制項,並保持忠實 MVC 設計模式的精神。 幸運的是,架構版本 2,沒有更好的東西。

控制對。 模型

您可以像這個文字方塊的 WebForm 控制項視為使用者資料的簡單容器。 您可以將填入控制項的初始值,並對使用者顯示該值和您可以擷取使用者輸入或編輯由檢查控制項在回傳後任何值。 使用 [MVC 設計模式時 M (模型) 會播放此相同角色為資料的容器。 填入具有需要傳遞給一個使用者的資訊模型,它會執行回更新的值放入應用程式。 因此,模型是理想的位置,來快速的驗證規則和條件約束。

這裡 ’s 隨附全新的範例。 如果您建立新的 ASP.NET MVC 2 應用程式,尋找新的專案中控制站的其中一個就是 [AccountController。 它 ’s 負責處理新的使用者登錄要求,以及登入] 和 [變更密碼的要求。 這些動作的每個使用專用的模型物件。 您可以在 [模型] 資料夾中 AccountModels.cs 檔案中找到這些模型。 比方說 RegisterModel 類別的驗證規則而看起來會像這樣:

public class RegisterModel
{
  public string UserName { get; set; }
  public string Email { get; set; }
  public string Password { get; set; }
  public string ConfirmPassword { get; set; }
}

登錄動作的 [AccountController 採用這個 RegisterModel 類別的執行個體做為參數:

[HttpPost]
public ActionResult Register(RegisterModel model)
{
    // ...
}

如果模型為有效,註冊動作會轉送到可以建立新使用者的服務型號資訊。

RegisterModel 模型是一個很好的範例,檢視特定模型 或檢視模型。 它不 ’s 模型,設計來運作與特定資料庫表格、 Web 服務呼叫或商務物件。 而是,它設計來搭配特定的檢視 (Register.aspx 檢視, 的 圖 1 所示的其中一部份)。 在模型上的每個屬性會對應至檢視中輸入控制項。 我建議您在使用檢視模型如它們簡化許多案例中 MVC 開發包括驗證。


圖 1 的 註冊資訊

模型和中繼資料

當使用者輸入帳戶資訊在檢視中的登錄時,MVC 架構可確保使用者提供使用者名稱] 和 [電子郵件。 架構也確保的密碼] 及 [ConfirmPassword 字串符合,所輸入的密碼也至少六個字元長。 它如何? 這所有 藉由檢查並做附加到 RegisterModel 類別的中繼資料。 圖 2 顯示 RegisterModel 類別以顯示其驗證屬性。

圖 2 的 RegisterModel 類別,以驗證屬性

[PropertiesMustMatch("Password", "ConfirmPassword", 
  ErrorMessage = "The password and confirmation password do not match.")]
public class RegisterModel
{
  [Required]        
  public string UserName { get; set; }

  [Required]
  public string Email { get; set; }

  [Required]
  [ValidatePasswordLength]
  public string Password { get; set; }

  [Required]
  public string ConfirmPassword { get; set; }
}

當使用者送出登錄檢視時,預設模型繫結器,在 ASP.NET MVC 中的將會嘗試建置 RegisterModel 類別中,以做為參數傳遞給 AccountController ’s 註冊動作的新執行個體。 模型繫結器 (Binder) 擷取在目前的要求來填入 RegisterModel 物件中的資訊。 比方說它可以自動找出名為使用者名稱,HTML 輸入控制項的張貼值並使用該值填入 RegisterModel] 的 [使用者名稱] 屬性。 這種情形在 ASP.NET MVC 後已經版本 1.0,所以如果您已經使用架構 won’t 會新。

什麼是新版本 2 中是如何預設模型繫結器會也要求 中繼資料提供者 是否沒有任何中繼資料可供 RegisterModel 物件使用。 這個處理程序最後會產生 ModelMetaData 衍生的物件,其目的為描述在該模型相關聯的驗證規則不僅與顯示在檢視中模型的相關資訊。 ASP.NET 團隊成員Brad Wilson 有深入的系列的柱子上此模型中繼資料可能會如何影響透過範本的模型的顯示。 數列中的第一個張貼位於 bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-1-introduction.html

一旦模型繫結器 (Binder) 都有一個與模型相關聯的 ModelMetaData 物件,它可以使用驗證中繼資料內驗證模型物件。 根據預設值,ASP.NET MVC 會使用資料附注屬性喜歡 [必要] 從中繼資料。 當然 ASP.NET MVC 是隨插即用且可延伸,因此若想策劃模型中繼資料為不同的來源,您就可以實作自己的中繼資料提供者。 Ben Scheirman 標題為發行項中有一些很棒的資訊,有關這個主題 「 自訂 ASP.NET MVC 2 — 中繼資料與驗證,」 可在 dotnetslackers.com/articles/aspnet/customizing-asp-net-mvc-2-metadata-and-validation.aspx

資料註釋

為簡要離題,您可以建置自己的驗證屬性,如同我們稍後,看到,但是 [必要] 是數個即時 System.ComponentModel.DataAnnotations 組件內的標準驗證屬性的其中一個。 圖 3 會顯示驗證屬性的完整清單,從註解組件。

圖 3 的 註釋組件的驗證屬性

特質 描述
StringLength 指定字串資料欄位中所允許的最大長度。
Required 指出需要使用資料欄位值。
RegularExpression 指定資料欄位值必須符合指定的規則運算式。
範圍 指定資料欄位的值中數字範圍條件約束。
DataType 指定要與資料欄位 (其中一個列舉的資料類型值的 EmailAddress、 URL 或密碼等) 關聯的其他型別名稱。

Microsoft.NET Framework 跨這些資料附註屬性快速成為作用廣泛。 不只可以使用 ASP.NET MVC 應用程式,但 ASP.NET 動態資料中的這些屬性,Silverlight 和 Silverlight RIA 服務瞭解它們也。

檢視驗證

與就地驗證中繼資料,錯誤會自動出現在檢視中於使用者輸入不正確的資料時。 圖 4 顯示登錄檢視樣貌使用者時碰到登錄未提供任何資訊。


圖 4 驗證失敗

顯示在 的 圖 4 所建置 ASP.NET MVC 2 包括 ValidationMessageFor 協助程式中使用某些新的 HTML 協助程式。 驗證失敗的特定資料欄位時,ValidationMessageFor 控制驗證訊息的位置。 圖 5 顯示摘錄從 Register.aspx 示範如何使用 ValidationMessageFor 和 ValidationSummary 協助程式。

圖 5 的 如何使用新的 HTML 程式

<% using (Html.BeginForm()) { %>
    <%= Html.ValidationSummary(true, "Account creation was unsuccessful. " +
    "Please correct the errors and try again.") %>
    <div>
        <fieldset>
            <legend>Account Information</legend>
            
            <div class="editor-label">
                <%= Html.LabelFor(m => m.UserName) %>
            </div>
            <div class="editor-field">
                <%= Html.TextBoxFor(m => m.UserName) %>
                <%= Html.ValidationMessageFor(m => m.UserName) %>
            </div>

自訂驗證

不是所有 RegisterModel 類別上的 [驗證] 屬性都是從 Microsoft ’s 資料註釋組件的屬性。 [PropertiesMustMatch] 和 [ValidatePasswordLength] 是定義自訂屬性尋找在相同存放 RegisterModel 類別的 AccountModel.cs 檔案。 並不需要擔心還得自訂中繼資料提供者或中繼資料類別如果您只是要提供自訂驗證規則。 您需要做的就是衍生自抽象類別 ValidationAttribute,並提供 IsValid 方法的實作。 的 圖 6 所示 ValidatePasswordLength 屬性的實作。

圖 6 的 ValidatePasswordLength 屬性實作

[AttributeUsage(AttributeTargets.Field | 
                AttributeTargets.Property, 
                AllowMultiple = false, 
                Inherited = true)]
public sealed class ValidatePasswordLengthAttribute 
    : ValidationAttribute
{
    private const string _defaultErrorMessage = 
        "’{0}’ must be at least {1} characters long.";

    private readonly int _minCharacters = 
        Membership.Provider.MinRequiredPasswordLength;

    public ValidatePasswordLengthAttribute()
        : base(_defaultErrorMessage)
    {
    }

    public override string FormatErrorMessage(string name)
    {
        return String.Format(CultureInfo.CurrentUICulture, 
            ErrorMessageString,
            name, _minCharacters);
    }

    public override bool IsValid(object value)
    {
        string valueAsString = value as string;
        return (valueAsString != null && 
            valueAsString.Length >= _minCharacters);
    }
}

其他屬性,PropertiesMustMatch,是一個很好的範例的驗證屬性,您可以套用在類別層級來執行交叉屬性驗證。

用戶端驗證

我們看 RegisterModel 驗證到目前為止所有花上都放置伺服器。 幸運的是,它 ’s 容易太啟用用戶端的驗證。 我試著使用不論何時儘可能的用戶端驗證,因為它可以提供使用者快速意見反應時將卸載一些工作,從我的伺服器。 伺服器端邏輯必須停留在不過,位置,以防有人 doesn’t 有指令碼在瀏覽器中啟用 (或故意正在嘗試將錯誤資料傳送到伺服器)。

啟用用戶端驗證是一個具有兩個步驟的程序。 步驟 1 正在確認該檢視表含有適當驗證指令碼。 您所需要的所有指令碼存放在新的 MVC 應用程式的 [指令碼] 資料夾。 MicrosoftAjax.js 指令碼是 Microsoft AJAX 程式庫的核心,而且需要包含第一個指令碼。 第二個指令碼是 MicrosoftMvcValidation.js。 通常,我新增一個 ContentPlaceHolder 到我 MVC 應用程式 ’s 主版頁面] 來保留指令碼,如下所示:

<head runat="server">
    <title><asp:ContentPlaceHolder ID="TitleContent" runat=
"server" /></title>
    <link href="../../Content/Site.css" rel="stylesheet" type=
"text/css" />

    <asp:ContentPlaceHolder ID="Scripts" runat="server">
       
    </asp:ContentPlaceHolder>
    
</head>

檢視表可以再包含它需要使用內容控制項指令碼。 下列程式碼會確保驗證指令碼都存在:

<asp:Content ContentPlaceHolderID="Scripts" runat="server">
    <script src="../../Scripts/MicrosoftAjax.js" 
            type="text/javascript"></script>
    <script src="../../Scripts/MicrosoftMvcValidation.js" 
            type="text/javascript"></script>
</asp:Content>

第二個步驟中使用用戶端驗證是叫用 EnableClientValidation HTML Helper 方法,在檢視您需要驗證支援。 請確定叫用這個方法使用 BeginForm HTML] 協助人員之前,如下所示:

<%
       Html.EnableClientValidation(); 
       using (Html.BeginForm())
        {
     %>
     
     <!-- the rest of the form ... -->
     
     <% } %>

請注意,用戶端驗證邏輯只適用於內建驗證屬性。 對於 Register] 檢視中,這表示用戶端驗證可確保必要的欄位存在,但不是會知道如何驗證密碼長度,或確認兩個密碼欄位相符。 幸運的是,它 ’s 可以輕鬆地加入 ASP.NET MVC JavaScript 驗證架構插入的自訂 JavaScript 驗證邏輯。 Phil Haack 對他網誌,「 ASP.NET MVC 2 自訂驗證,」 位於 haacked.com/archive/2009/11/19/aspnetmvc2-custom-validation.aspx 詳細資料。

換行,您可以看到內建支援驗證的常見案例是龐大的新加入 ASP.NET MVC 2。 不只是驗證規則可以輕鬆地透過模型物件上的屬性中加入,而且驗證功能本身是有彈性且容易擴充。 開始接受利用這些功能來節省時間和線條與下一個 ASP.NET MVC 應用程式的程式碼。

K. Scott Allen 是 Pluralsight 技術人員的成員和 OdeToCode founder。 您可以在 scott@OdeToCode.com 到達 Allen、 讀取他的部落格,在 odetocode.com/blogs/scott 或依照他有關 Twitter 在 twitter.com/OdeToCode。

多虧給來檢閱這份文件的技術專家下列: Brad Wilson