这样的验证看上去多美——在参数上应用验证特性

如果可以把基于特性的Model验证应用在参数就好了,如图:

 

通过右键查看定义,可以明显看出RangeAttribute是可以应用在参数上的,如图:

 

看到这里有木有很嗨皮,就这么简单就是实现了,咳咳如果这样就完了,那我还写这篇干嘛呢,嘻嘻..

其实这样是不会执行验证的,验证永远都是通过的,不信看图(有图才有真相):

 

那为啥可以应用在参数上,但是就是不执行验证呢?不要着急请听我慢慢道来。

是这样的:模型验证是在模型绑定的时候执行的,验证信息都是保存在了ModelMetadata里(看下面的图),里面只包含一些模型的验证和一起洗其他与模型相关的信息,我们定义的参数的特性属于参数信息,并不在模型元数据里面,所以验证的时候根本就没有我们定义的特性验证信息。

ModelMetadata

 

说道这里一切的原因都清楚,要想实现基于特性的验证应用在参数,就是简简单单把我们定义的特性放进模型元数据里就行了啊。

第一步:把参数上的特性保存起来

要想获取参数特性可以通过ParameterDescriptor来得到,如图

 

要想获取ParameterDescriptor可以通过ControllerActionInvoker的GetParameterValue方法获取。如图

我们通过GetparameterValue方法,把参数parameterDescription保存在路由里。

 

上图我们是实现了一个自定义的ActionInvoker。在Controller里有一个CreateActionInvoker方法是用来创建ActionInvoker,我们重写这个方法返回我们自定义的ActionInvoker,如图

至此参数的信息已经被我们保存起来。

 

第二步:把参数的特性生成ModelValidator

我们自定义一个ModelValidatorProvider来提供ModelValidator如图

ModelValidator是由ModelValidatorProvider来提供,所以我继承了DataAnnotationsModelValidatorProvider,在重写的GetValidators方法中我们将之前保存的ParameterDescriptor提取出来,从中获取attribute与已有的attributes合并,生成ModelValidator。

此刻参数上的特性已经生成ModelValidator,并保存在ModelMetadata中

 

第三不:注册ParameterValidationModelValidatorProvider

在注册ParameterValidationModelValidatorProvider之前需要将现有的DataAnnotationsModelValidatorProvider移除。如图:

 

此刻其实参数验证还是不会有效果的,原因是模型绑定是模型验证不会对简单类型实施验证。所以我要自定义一个模型绑定。

第四部:自定义模型绑定

我们继承了默认的模型绑定,重写BindModel方法,如果是复杂类型或者modelnull,就直接返回model,应为我们这个只是针对简单类型验证。空也没必要验证。

 

第五部:实例演示,如图

 

 ps:感谢蒋金楠老师的博客http://www.cnblogs.com/artech/archive/2012/06/11/data-annotations-model-validation-04.html

posted @ 2015-12-20 22:52  世上最帅的程序员  阅读(707)  评论(1编辑  收藏  举报