ASP.NET MVC下的四种验证编程方式[续篇]

2019-05-26 02:52:00丽君

 public class DataAnnotationsModelValidator : ModelValidator
 { 
 public DataAnnotationsModelValidator(ModelMetadata metadata, ControllerContext context, ValidationAttribute attribute);
 public override IEnumerable<ModelClientValidationRule> GetClientValidationRules();
 public override IEnumerable<ModelValidationResult> Validate(object container);
 
 protected internal ValidationAttribute Attribute { get; }
 protected internal string   ErrorMessage { get; }
 public override bool   IsRequired { get; }
 }

DataAnnotationsModelValidator的提供者为DataAnnotationsModelValidatorProvider,关于ValidationAttribute、DataAnnotationsModelValidator和DataAnnotationsModelValidatorProvider的详细内容可以参考之前写的三篇文章。

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

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

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

三、ValidatableObjectAdapter

如果被验证的数据类型实现了IValidatable接口,ASP.NET MVC会自动调用实现的Validate方法对其实施验证,此时创建的ModelValidator是一个ValidatableObjectAdapter对象。ValidatableObjectAdapter定义如下,其Validate方法的实现逻辑很简单:它直接调用被验证对象的Validate方法,并将返回的ValidationResult对象转换成ModelValidationResult类型。

 public class ValidatableObjectAdapter : ModelValidator
 {
 public ValidatableObjectAdapter(ModelMetadata metadata, ControllerContext context);
 public override IEnumerable<ModelValidationResult> Validate(object container);
 }

虽然ValidatableObjectAdapter继承自ModelValidator,但是ASP.NET MVC貌似没有将其视为一个真正意义上的ModelValidator,而是将其视为一个“适配器(Adapter)”。ASP.NET MVC也没有为ValidatableObjectAdapter定义单独的ModelValidatorProvider,它的提供者其实是上面提到过的DataAnnotationsModelValidatorProvider。

四、DataErrorInfoModelValidator

如果我们让数据类型实现IDataErrorInfo接口,可以利用实现的Error属性和索引提供针对自身以及所属数据成员的验证错误信息。针对这样的数据类型,ASP.NET MVC最终会创建一个DataErrorInfoModelValidator对象来对其实施验证,DataErrorInfoClassModelValidator和DataErrorInfoPropertyModelValidator是两个具体的DataErrorInfoModelValidator。

DataErrorInfoClassModelValidator和DataErrorInfoPropertyModelValidator是两个内部类型。前者针对容器对象自身实施验证,所以它只需要从实现的Error属性中提取错误消息并将其转换成返回的ModelValidationResult对象。后者则专门验证容器对象的某个属性,它在实现的Validate方法中会利用属性名从实现的索引中提取相应的错误消息并将其转换成返回的ModelValidationResult对象。

 internal sealed class DataErrorInfoClassModelValidator : ModelValidator
 {
 public DataErrorInfoClassModelValidator(ModelMetadata metadata, ControllerContext controllerContext);
 public override IEnumerable<ModelValidationResult> Validate(object container);
 } 
 internal sealed class DataErrorInfoPropertyModelValidator : ModelValidator
 {
 public DataErrorInfoPropertyModelValidator(ModelMetadata metadata, ControllerContext controllerContext);
 public override IEnumerable<ModelValidationResult> Validate(object container);
 }