822
技術社區[雲棲]
ASP.NET MVC以ModelValidator為核心的Model驗證體係: ModelValidator
旨在為目標Action方法的執行綁定輸入參數的Model綁定過程伴隨著對Model的驗證。借助相應的驗證特性,我們可以直接以聲明的方式在Model類型上定義驗證規則,這些規則將會作為Model元數據的一部分。具體在Model綁定過程中,ModelBinder通過ValueProvider為Model對象的某個屬性提供相應屬性值之後,會根據定義在基於該屬性的Model元數據的驗證規則實施驗證。ASP.NET MVC的整個Model驗證係統以組件ModelValidator為核心,或者說Model對象的驗證最終通過某個ModelValidator對象來完成,所以我們有必要先來認識一下ModelValidator以及背後的提供機製。[本文已經同步到《How ASP.NET MVC Works?》中]
目錄
一、ModelValidator
二、DataAnnotationsModelValidator
三、ClientModelValidator
四、DataErrorInfoModelValidator
五、ValidatableObjectAdapter
在ASP.NET MVC應用編程接口中,所有的ModelValidator都直接或者間接地繼承自抽象類型ModelValidator。如下麵的代碼片斷所示,ModelValidator具有一個布爾類型的隻讀屬性IsRequired,表示該ModelValidator是否是對目標數據進行必要性的驗證,默認返回False。GetClientValidationRules返回一個元素類型為ModelClientValidationRule的集合。ModelClientValidationRule是對客戶端驗證規則的封裝,我們會在進行客戶端驗證時對其進行詳細介紹。
1: public abstract class ModelValidator
2: {
3: //其他成員
4: public virtual IEnumerable<ModelClientValidationRule> GetClientValidationRules();
5: public abstract IEnumerable<ModelValidationResult> Validate(object container);
6:
7: public virtual bool IsRequired { get; }
8: }
真正對目標數據實施驗證是通過調用Validate方法來完成的,而該方法的輸入參數container表示的正式被驗證的對象。該Validate返回一個表示驗證結果的元素類型為ModelValidationResult的集合,該類型的定義如下所示。
1: public class ModelValidationResult
2: {
3: public ModelValidationResult();
4:
5: public string MemberName { get; set; }
6: public string Message { get; set; }
7: }
ModelValidationResult具有兩個字符串類型的屬性MemberName和Message,前者代表被驗證數據成員的名稱,後者表示錯誤消息。一般來說,當它們用於驗證某個複雜類型對象的時候,針對於類型本身驗證返回的ModelValidationResult對象的MemberName屬性為空字符串;而對於針對屬性驗證來說,屬性名稱直接作為MemberName屬性值。
ModelClientValidationRule集合隻有在驗證失敗的情況下才會返回。如果目標數據符合所有的驗證規則,Validate方法會直接返回Null或者一個空ModelValidationResult集合。值得一提的是,我們在調用ModelValidator的Validate方法確定目標數據是否通過驗證時,有時候會將方法返回值和定義在類型ValidationResult中具有如下定義的靜態隻讀字段Success進行比較。實際上,表示驗證成功的Success字段值就是。
1: public class ValidationResult
2: {
3: //其他成員
4: public static readonly ValidationResult Success;
5: }
稍微了解ASP.NET MVC的讀者應該知道,我們可以通過數據類型的某個屬性上應用相應的驗證標注特性(比如RequiredAttribute、RangeAttribute和RegularExpressionAttribute等)的方式來定義相應的驗證規則,這是ASP.NET MVC 提供的默認Model驗證方式。這種基於數據標注(Data Annotation)特性的驗證對應的ModelValidator類型為DataAnnotationsModelValidator,我們會在後續的文章中對其進行單獨介紹。
ClientModelValidator是定義在程序集System.Web.Mvc.dll中的內部類型,在客戶端用於數據類型的驗證。如下麵的代碼片斷所示,在構造函數中除了指定Model元數據和Controller上下文之外,還需要以字符串的形式指定驗證類型(數據類型)和錯誤消息。
1: internal class ClientModelValidator : ModelValidator
2: {
3: public ClientModelValidator(ModelMetadata metadata, ControllerContext controllerContext, string validationType,string errorMessage);
4: public sealed override IEnumerable<ModelClientValidationRule> GetClientValidationRules();
5: public sealed override IEnumerable<ModelValidationResult> Validate(object container);
6: }
由於ClientModelValidator僅限於客戶端驗證,其Validate方法(服務端驗證)總是返回一個空的ModelValidationResult集合,而GetClientValidationRules方法會根據指定的驗證類型和錯誤消息生成相應的客戶端驗證規則。
ClientModelValidator具有兩個繼承者,分別是數值類型和日期類型進行客戶端驗證的和。如下麵的代碼片斷所示,這兩個ClientModelValidator用於表示驗證數據類型的字符串分別是“”和“”。而表示錯誤消息的字符串是從內部維護的資源文件中獲取的。這實際上帶來了一個問題,。
1: internal sealed class NumericModelValidator :ClientModelValidator
2: {
3: public NumericModelValidator(ModelMetadata metadata, ControllerContext controllerContext)
4: : base(metadata, controllerContext, "", ClientDataTypeModelValidatorProvider.GetFieldMustBeNumericResource(controllerContext))
5: {
6: }
7: }
8:
9: internal sealed class DateModelValidator :ClientModelValidator
10: {
11: public DateModelValidator(ModelMetadata metadata, ControllerContext controllerContext)
12: : base(metadata, controllerContext, "", ClientDataTypeModelValidatorProvider.GetFieldMustBeDateResource(controllerContext))
13: {
14: }
15: }
在System.ComponentModel命名空間下定義了一個名為IDataErrorInfo的接口,該接口提供了一種標準的錯誤信息定製方式。如下麵的代碼片斷所示,IDataErrorInfo具有兩個成員,隻讀屬性Error用於獲取基於自身的錯誤消息,而隻讀索引用於返回指定數據成員的錯誤消息。
1: public interface IDataErrorInfo
2: {
3: string Error { get; }
4: string this[string columnName] { get; }
5: }
ASP.NET MVC的Model驗證係統為實現了IDataErrorInfo接口的數據對象的驗證定義專門的ModelValidator。具體來說,對於一個類型實現了IDataErrorInfo接口的數據對象,我們可以通過DataErrorInfoClassModelValidator對該對象本身實施驗證,DataErrorInfoClassModelValidator會將Error屬性表示的錯誤消息轉換為表示驗證結果的ModelValidationResult對象。而對於該對象的屬性的驗證則采用另一個類型為DataErrorInfoPropertyModelValidator對象,DataErrorInfoPropertyModelValidator會將屬性名稱作為調用索引的參數從而獲得相應的錯誤消息,並進一步轉換成ModelValidationResult對象返回。DataErrorInfoPropertyModelValidator和DataErrorInfoPropertyModelValidator都是定義在程序集System.Web.Mvc.dll中的內部類型,並不對外公布。
在System.ComponentModel.DataAnnotations命名空間下定義了一個IValidatableObject接口,它代表另外一種驗證的模式,我個人將其稱為“自我驗證”,即數據對象自行實現針對自身的驗證。如下麵的代碼片斷所示,針對自身的驗證實現在IValidatableObject的Validate方法中。
1: public interface IValidatableObject
2: {
3: IEnumerable<ValidationResult> Validate(ValidationContext validationContext);
4: }
ASP.NET Model驗證係統定義了專門的ModelValidator來驗證種實現了IValidatableObject接口的數據對象,其類型為ValidatableObjectAdapter。由於被驗證本身已經將驗證實現在了Validate方法中,所以ValidatableObjectAdapter隻需要調用該方法並將驗證結果從ValidationResult類型轉換成ModelValidationResult類型即可。
1: public class ValidatableObjectAdapter : ModelValidator
2: {
3: public ValidatableObjectAdapter(ModelMetadata metadata, ControllerContext context);
4: public override IEnumerable<ModelValidationResult> Validate(object container);
5: }
ASP.NET MVC以ModelValidator為核心的Model驗證體係: ModelValidator
ASP.NET MVC以ModelValidator為核心的Model驗證體係: ModelValidatorProvider
ASP.NET MVC以ModelValidator為核心的Model驗證體係: ModelValidatorProviders
微信公眾賬號:大內老A
微博:www.weibo.com/artech
如果你想及時得到個人撰寫文章以及著作的消息推送,或者想看看個人推薦的技術資料,可以掃描左邊二維碼(或者長按識別二維碼)關注個人公眾號(原來公眾帳號蔣金楠的自媒體將會停用)。
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁麵明顯位置給出原文連接,否則保留追究法律責任的權利。
最後更新:2017-10-26 11:34:00