ASP.NET MVC基于标注特性的Model验证:DataAnnotationsModelValidatorProvider

简介:

DataAnnotationsModelValidator最终是通过它对应的ModelValidatorProvider,即DataAnnotationsModelValidatorProvider创建的。通过前面的介绍我们知道它是AssociatedValidatorProvider的子类,后者在用于获取ModelValidator的GetValidators方法中已经根据指定的Model元数据所有特性创建出来,DataAnnotationsModelValidator只需要从中筛选出继承自ValiationAttribute的验证特性并创建对象的DataAnnotationsModelValidator就可以了。[本文已经同步到《How ASP.NET MVC Works?》中]

目录
DataAnnotationsModelValidator
基于ValidationAttribute的ModelValidator的创建
基于IValidatableObject的ModelValidator的创建
默认的ModelValidator创建机制
对ModelValidator创建方式的定制

DataAnnotationsModelValidator

我们现在结合DataAnnotationsModelValidator的相关定义来讨论一下具体的ModelValidator提供机制。如下面的代码片断所示,DataAnnotationsModelValidatorProvider具有两个静态的字段AttributeFactories和DefaultAttributeFactory,后者是一个DataAnnotationsModelValidationFactory委托,前者是以此委托为Value以Type对象为Key的字典。

   1: public class DataAnnotationsModelValidatorProvider : AssociatedValidatorProvider
   2: {
   3:     //其他成员
   4:     internal static readonly Dictionary<Type, DataAnnotationsModelValidationFactory> AttributeFactories;
   5:     internal static DataAnnotationsModelValidationFactory DefaultAttributeFactory;
   6:  
   7:     internal static DataAnnotationsValidatableObjectAdapterFactory DefaultValidatableFactory;
   8:     internal static readonly Dictionary<Type, DataAnnotationsValidatableObjectAdapterFactory> ValidatableFactories;
   9:     
  10:     protected override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, HttpActionContext actionContext, IEnumerable<Attribute> attributes);
  11: }
  12:  
  13: public delegate ModelValidator DataAnnotationsModelValidationFactory(ModelMetadata metadata, ControllerContext context, ValidationAttribute attribute);
  14:  
  15: public delegate ModelValidator DataAnnotationsValidatableObjectAdapterFactory(ModelMetadata metadata, ControllerContext context);

基于ValidationAttribute的ModelValidator的创建

委托DataAnnotationsModelValidationFactory根据ModelMetadata、ControllerContext和ValidationAttribute返回一个ModelValidator对象,而字段AttributeFactories表示的字典对象的Key是具体的验证特性的类型,也就是说它维护一个ValidationAttribute特性类型和对应ModelValidator工厂的匹配关系。在重写的GetValidators方法中,针对指定的每一个ValidationAttribute,它先根据其类型从AttributeFactories中获取一个对应的DataAnnotationsModelValidationFactory委托,如果该委托存在,则用它来创建相应的ModelValidator对象;否则就采用字段DefaultAttributeFactory表示的DataAnnotationsModelValidationFactory委托来进行ModelValidator的创建

基于IValidatableObject的ModelValidator的创建

除了AttributeFactories和DefaultAttributeFactory,DataAnnotationsModelValidatorProvider还具有DefaultValidatableFactory和ValidatableFactories这两个静态属性,它们用于针对可验证对象(实现了IValidatableObject接口)的ModelValidator的创建。DataAnnotationsModelValidator的类型是另外一个类型为DataAnnotationsValidatableObjectAdapterFactory的委托,该委托根据ModelMetadata和ControllerContext创建相应的ModelValidator。ValidatableFactories是一个以此委托为Value,以Type对象为Key的字典。

当DataAnnotationsModelValidatorProvider完成了针对基于验证特性的ModelValidator的创建之后,如果根据Model元数据解析出来的Model类型实现了IValidatableObject接口,那么先从字典ValidatableFactories中根据此类型获取一个对应的DataAnnotationsValidatableObjectAdapterFactory委托,如果匹配的委托对象存在,则用其进行ModelValidator的创建;否则采用通过字段DefaultValidatableFactory表示的默认工厂来创建相应的ModelValidator对象

默认的ModelValidator创建机制

在DataAnnotationsModelValidatorProvider类型被加载的时候,上述的四个字段会在静态构造函数调用时被初始化。从如下的代码片断可看出,对于一般的ValidationAttribute,对应的ModelValidator是一个DataAnnotationsModelValidator对象(DefaultAttributeFactory字段);针对RangeAttribute、RegularExpressionAttribute 、RequiredAttribute和StringLengthAttribute这四种验证特性,它们对应的适配ModelValidator会被创建出来。而对于可验证对象来说,默认情况下提供的ModelValidator列表中还包含一个ValidatableObjectAdapter对象。

   1: public class DataAnnotationsModelValidatorProvider : AssociatedValidatorProvider
   2: {
   3:     //其他成员
   4:     static DataAnnotationsModelValidatorProvider()
   5:     {
   6:         //1、DefaultAttributeFactory
   7:         DefaultAttributeFactory = (metadata, context, attribute) => new DataAnnotationsModelValidator(metadata, context, attribute);
   8:  
   9:         //2、AttributeFactories
  10:         Dictionary<Type, DataAnnotationsModelValidationFactory> dictionary = new Dictionary<Type, DataAnnotationsModelValidationFactory>();
  11:         dictionary.Add(typeof(RangeAttribute), (metadata, context, attribute) => new RangeAttributeAdapter(metadata, context, (RangeAttribute)attribute));
  12:         dictionary.Add(typeof(RegularExpressionAttribute), (metadata, context, attribute) => new RegularExpressionAttributeAdapter(metadata, context, (RegularExpressionAttribute)attribute));
  13:         dictionary.Add(typeof(RequiredAttribute), (metadata, context, attribute) => new RequiredAttributeAdapter(metadata, context, (RequiredAttribute)attribute));
  14:         dictionary.Add(typeof(StringLengthAttribute), (metadata, context, attribute) => new StringLengthAttributeAdapter(metadata, context,(StringLengthAttribute)attribute));
  15:         AttributeFactories = dictionary;
  16:  
  17:         //3、DefaultValidatableFactory
  18:         DefaultValidatableFactory = (metadata, context) => new ValidatableObjectAdapter(metadata, context);
  19:  
  20:         //4、ValidatableFactories
  21:         ValidatableFactories = new Dictionary<Type, DataAnnotationsValidatableObjectAdapterFactory>();
  22:     }
  23: }

对ModelValidator创建方式的定制

DataAnnotationsModelValidatorProvider四个基于委托的静态字段体现了其采用的ModelValidator提供机制。由于它们都是内部字段,我们不能直接对其进行操作,但是如下所示的一系列静态方法在DataAnnotationsModelValidatorProvider中定义出来,使我们可以按照具体的需要对默认的ModelValidator进行定义。

   1: public class DataAnnotationsModelValidatorProvider : AssociatedValidatorProvider
   2: {
   3:     //其他成员  
   4:    public static void RegisterAdapter(Type attributeType, Type adapterType);
   5:    public static void RegisterAdapterFactory(Type attributeType, DataAnnotationsModelValidationFactory factory);
   6:    public static void RegisterDefaultAdapter(Type adapterType);
   7:    public static void RegisterDefaultAdapterFactory(DataAnnotationsModelValidationFactory factory);
   8:  
   9:    public static void RegisterDefaultValidatableObjectAdapter(Type adapterType);
  10:    public static void RegisterDefaultValidatableObjectAdapterFactory(DataAnnotationsValidatableObjectAdapterFactory factory);
  11:    public static void RegisterValidatableObjectAdapter(Type modelType, Type adapterType);
  12:    public static void RegisterValidatableObjectAdapterFactory(Type modelType, DataAnnotationsValidatableObjectAdapterFactory factory);
  13: }

对于上面的8个静态方法,除了RegisterDefaultAdapter和RegisterValidatableObjectAdapter之外,其余的都很好理解。RegisterDefaultAdapter用于注册一个默认的针对验证特性的ModelValidator类型,该类型必须具有一个参数类型列表为ModelMetadata、ControllerContext和Attribute的构造函数。如果根据 验证特性的类型找到了匹配的DataAnnotationsModelValidationFactory委托对象,相应的参数会被传入该构造函数并最终创建一个我们注册的ModelValidator对象。

RegisterValidatableObjectAdapter和RegisterDefaultAdapter比较类似,用于注册一个默认的针对可验证对象类型的ModelValidator,有该类型必须具有一个参数类型列表为ModelMetadata和ControllerContex的构造函数。如果根据 验证特性的类型找到了匹配的DataAnnotationsValidatableObjectAdapterFactory委托对象,相应的参数会被传入该构造函数并最终创建一个我们注册的ModelValidator对象。

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,多种验证规则


作者:蒋金楠
微信公众账号:大内老A
微博: www.weibo.com/artech
如果你想及时得到个人撰写文章以及著作的消息推送,或者想看看个人推荐的技术资料,可以扫描左边二维码(或者长按识别二维码)关注个人公众号(原来公众帐号 蒋金楠的自媒体将会停用)。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
相关文章
|
2月前
|
监控 前端开发 API
一款基于 .NET MVC 框架开发、功能全面的MES系统
一款基于 .NET MVC 框架开发、功能全面的MES系统
|
5月前
|
开发框架 前端开发 JavaScript
ASP.NET MVC 教程
ASP.NET 是一个使用 HTML、CSS、JavaScript 和服务器脚本创建网页和网站的开发框架。
66 7
|
5月前
|
存储 开发框架 前端开发
ASP.NET MVC 迅速集成 SignalR
ASP.NET MVC 迅速集成 SignalR
111 0
|
6月前
|
开发框架 前端开发 .NET
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
82 0
|
6月前
|
开发框架 前端开发 安全
ASP.NET MVC 如何使用 Form Authentication?
ASP.NET MVC 如何使用 Form Authentication?
|
6月前
|
开发框架 .NET
Asp.Net Core 使用X.PagedList.Mvc.Core分页 & 搜索
Asp.Net Core 使用X.PagedList.Mvc.Core分页 & 搜索
185 0
|
9月前
|
开发框架 前端开发 .NET
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
244 0
|
9月前
|
开发框架 前端开发 JavaScript
JavaScript云LIS系统源码ASP.NET CORE 3.1 MVC + SQLserver + Redis医院实验室信息系统源码 医院云LIS系统源码
实验室信息系统(Laboratory Information System,缩写LIS)是一类用来处理实验室过程信息的软件,云LIS系统围绕临床,云LIS系统将与云HIS系统建立起高度的业务整合,以体现“以病人为中心”的设计理念,优化就诊流程,方便患者就医。
97 0
|
9月前
|
开发框架 前端开发 .NET
C# .NET面试系列六:ASP.NET MVC
<h2>ASP.NET MVC #### 1. MVC 中的 TempData\ViewBag\ViewData 区别? 在ASP.NET MVC中,TempData、ViewBag 和 ViewData 都是用于在控制器和视图之间传递数据的机制,但它们有一些区别。 <b>TempData:</b> 1、生命周期 ```c# TempData 的生命周期是短暂的,数据只在当前请求和下一次请求之间有效。一旦数据被读取,它就会被标记为已读,下一次请求时就会被清除。 ``` 2、用途 ```c# 主要用于在两个动作之间传递数据,例如在一个动作中设置 TempData,然后在重定向到另
406 5
|
存储 开发框架 前端开发
[回馈]ASP.NET Core MVC开发实战之商城系统(五)
经过一段时间的准备,新的一期【ASP.NET Core MVC开发实战之商城系统】已经开始,在之前的文章中,讲解了商城系统的整体功能设计,页面布局设计,环境搭建,系统配置,及首页【商品类型,banner条,友情链接,降价促销,新品爆款】,商品列表页面,商品详情等功能的开发,今天继续讲解购物车功能开发,仅供学习分享使用,如有不足之处,还请指正。
185 0

热门文章

最新文章