ASP.NET MVC基于标注特性的Model验证:DataAnnotationsModelValidator
对于ASP.NET MVC基于标注特性的Model验证,很多人只知道应用在数据类型及其属性上用于定义验证规则和错误消息的ValidationAttribute。通过《ASP.NET MVC以ModelValidator为核心的Model验证体系: ModelValidator》的介绍,我们知道了最终用于进行Model验证的是一个叫做ModelValidator的组件。ValidationAttribute对应的ModelValidator为DataAnnotationsModelValidator,这篇简短的文章为你介绍ASP.NET MVC是如何针对Validation来创建DataAnnotationsModelValidator,以及后者如何利用前者实施Model验证的。[本文已经同步到《How ASP.NET MVC Works?》中]
一、DataAnnotationsModelValidator
ModelValidator是真正用于进行Model验证的组件,上面介绍的验证特性最终被封装成DataAnnotationsModelValidator对象进而被应用到Model验证系统中。如下面的代码片断所示,被封装的ValidationAttribute通过只读属性Attribute表示,该属性在构造函数中被初始化。
1: public class DataAnnotationsModelValidator : ModelValidator
2: {
3: public DataAnnotationsModelValidator(ModelMetadata metadata, ControllerContext context, ValidationAttribute attribute);
4: public override IEnumerable<ModelClientValidationRule> GetClientValidationRules();
5:
6: public override IEnumerable<ModelValidationResult> Validate(object container)
7: {
8: ValidationContext validationContext = new ValidationContext(container ?? this.Metadata.Model, null, null)
9: {
10: DisplayName = this.Metadata.GetDisplayName()
11: };
12: ValidationResult validationResult = this.Attribute.GetValidationResult(this.Metadata.Model, validationContext);
13: if (validationResult != ValidationResult.Success)
14: {
15: ModelValidationResult iteratorVariable2 = new ModelValidationResult
16: {
17: Message = validationResult.ErrorMessage
18: };
19: yield return iteratorVariable2;
20: }
21: else
22: {
23: yield break;
24: }
25: }
26: protected ValidationAttribute Attribute { get; }
27: protected string ErrorMessage { get; }
28: public override bool IsRequired { get; }
29: }
我们给出了用于实施验证的核心方法Validate的完整定义。在该方法中,基于被验证对象(如果为Null则采用Model元数据的Model属性)创建出表示当前验证上下文的ValidationContext对象,并采用Model元数据的DisplayName属性作为该上下文的显示名称。最后直接调用被封装的ValidationAttribute的GetValidationResult方法对指定对象实施验证,如果返回的ValidationResult对象不为空,则以此创建ModelValidationResult对象并返回。
顺便在说说定义在DataAnnotationsModelValidator中的另外两个受保护只读属性的逻辑。用于返回错误消息的ErrorMessage属性来源对对ValidationAttribute的FormatErrorMessage方法的调用,而指定的参数就是当前Model元数据的DisplayName属性。由于只有RequiredAttribute才用于必需字段的验证,所有只有被封装ValidationAttribute为RequiredAttribute时其IsRequired属性返回True。
二、DataAnnotationsModelValidator<TAttribute>
DataAnnotationsModelValidator<TAttribute>是DataAnnotationsModelValidator的子类,其泛型参数为相应的ValidationAttribute的类型,下面的代码片断反映了其定义:
1: public class DataAnnotationsModelValidator<TAttribute> : DataAnnotationsModelValidator where TAttribute: ValidationAttribute
2: {
3: public DataAnnotationsModelValidator(ModelMetadata metadata, ModelBindingExecutionContext context, TAttribute attribute);
4: protected TAttribute Attribute { get; }
5: }
作为DataAnnotationsModelValidator与相应ValidationAttribute之间的适配,ASP.NET MVC为常用的ValidationAttribute(RequiredAttribute、RangeAttribute、RegularExpressionAttribute和StringLengthAttribute)定义相应的适配类型。如下面的代码片断所示,它们都是泛型的DataAnnotationsModelValidator<TAttribute>的子类。当我们将这些ValidationAttribute应用到Model类型时,真正用于Model验证的实际上就是这些作为适配的ModelValidator。
1: public class RequiredAttributeAdapter : DataAnnotationsModelValidator<RequiredAttribute>
2: {
3: public RequiredAttributeAdapter(ModelMetadata metadata, ControllerContext context, RequiredAttribute attribute);
4: public override IEnumerable<ModelClientValidationRule> GetClientValidationRules();
5: }
6:
7: public class RangeAttributeAdapter : DataAnnotationsModelValidator<RangeAttribute>
8: {
9: public RangeAttributeAdapter(ModelMetadata metadata, ControllerContext context, RangeAttribute attribute);
10: public override IEnumerable<ModelClientValidationRule> GetClientValidationRules();
11: }
12:
13: public class RegularExpressionAttributeAdapter : DataAnnotationsModelValidator<RegularExpressionAttribute>
14: {
15: public RegularExpressionAttributeAdapter(ModelMetadata metadata, ControllerContext context, RegularExpressionAttribute attribute);
16: public override IEnumerable<ModelClientValidationRule> GetClientValidationRules();
17: }
18:
19: public class StringLengthAttributeAdapter : DataAnnotationsModelValidator<StringLengthAttribute>
20: {
21: public StringLengthAttributeAdapter(ModelMetadata metadata, ControllerContext context, StringLengthAttribute attribute);
22: public override IEnumerable<ModelClientValidationRule>GetClientValidationRules();
23: }
ASP.NET MVC基于标注特性的Model验证:ValidationAttribute ASP.NET MVC基于标注特性的Model验证:DataAnnotationsModelValidator ASP.NET MVC基于标注特性的Model验证:DataAnnotationsModelValidatorProvider ASP.NET MVC基于标注特性的Model验证:将ValidationAttribute应用到参数上 ASP.NET MVC基于标注特性的Model验证:一个Model,多种验证规则
- JavaScript中的各种模块化规范
- 自己写个 Prisma
- Numpy|需要信手拈来的功能
- 数据库连接池极简教程
- 碎片化 | 第四阶段-35-Struts2-Spring结合jdbc实现查询列表-视频
- 碎片化 | 第四阶段-28-Struts2框架概述以及原理图解-视频
- nginx 负载均衡
- 机器学习算法应用中常用技巧-1
- 碎片化 | 第四阶段-29-Struts2入门示例1-视频
- nginx虚拟主机配置
- nginx rewrite
- 碎片化 | 第四阶段-30-Struts2入门示例流程梳理-视频
- 碎片化 | 第一阶段-01-基本常识-视频
- 你真的了解For循环吗?一道For循环Java面试题引发的思考
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法