MVC自定义验证特性
提到验证特性,我们不得不注意到ValidationAttribute这个类 , ValidationAttribute继承自Attribute基类,内部定义了验证机制。IsValid方法有两个虚方法:一个是返回bool值,一个是返回ValidationResult对象
public virtual bool IsValid(object value); protected virtual ValidationResult IsValid(object value, ValidationContext validationContext);
当我们需要定义自己的验证特性时,我想继承ValidationAttribute 那是不二之选了,与通过数据标注特性定义Model元数据类似,我们可以在作为Model的数据类型及其属性上应用相应的标注特性来定义Model验证规则。根据ErrorMessage属性,来定制显示错误消息,根据自己各项所需,定制出符合自己需求的验证特性。
IsValid方法可以根据自己的验证逻辑,对值进行验证,当值验证未能通过的时候,会显示出ErrorMessage属性的错误消息。
1 [__DynamicallyInvokable] 2 public string ErrorMessage { [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen imag e boundaries")] get; [__DynamicallyInvokable] set; } 3 [__DynamicallyInvokable] 4 public string ErrorMessageResourceName { [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method acr oss NGen image boundaries")] get; [__DynamicallyInvokable] set; } 5 [__DynamicallyInvokable] 6 public Type ErrorMessageResourceType { [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method acros s NGen image boundaries")] get; [__DynamicallyInvokable] set; }
当然,我们也可以采用资源的方式来保存错误消息定制,ErrorMessageResourceName/ErrorMessageResourceType 指定了错误消息资源项对应的名称和类型,ErrorMessageResourceType是一个只读属性,用于返回最终的错误消息文本。相比ErrorMessage,更具有优先级。
1 public override string FormatErrorMessage(string name) 2 { 3 return string.Format(CultureInfo.CurrentCulture, this.ErrorMessage, new object[] { name }); 4 }
为了让定义的资源文本能够最大限度地被重用,我们倾向于定义一个包含占位符的文本模板,通过重写FormatErrorMessage方法,对ErrorMessage中的字符串信息进行替换。该方法name,对应的是显示名称。
1 public interface IClientValidatable 2 { 3 IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context); 4 }
为了减少服务器资源的消耗,我们对前端也进行验证,所以,开始要注意到IClientValidatable接口了,IClientValidatable提供了GetClientValidationRules客户端验证,通过这个方法,可以在页面上生成相关的客户端验证规则,以达到前台的验证。
1 public override IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
GetClientValidationRules方法提供了两个参数模型元数据和控制器上下文,方法内部,可以通过metadata获得模型的一些属性值,比如显示名称。
该方法返回的是一个实体客户端验证规则,该规则类中有三个属性:
1 public string ErrorMessage { get; set; } 2 public IDictionary<string, object> ValidationParameters { get; } 3 public string ValidationType { get; set; }
ValidationType属性需设置成与客户端添加的验证方法一致,才能达到验证效果。
接着,我们往下走..
有时候,我们提交Html代码到服务器端的时候,会遇到“从客户端检测到有潜在危险的Request.Form 值”错误提示,这时候,我们怎么办呢?这时候可以开始动用模型元数据的RequestValidationEnabled,这个属性是设置是否启用验证值,当设置为flase的时候,可以提交html代码到后台,默认会为"<"等危险的尖角符号进行转码,我们来看看ModelMetadata这个类:
1 public virtual string Description {get;set;} //获取或设置描述文本 2 public virtual string DisplayName {get;set;} //当模型的名称显示时,在 UI 获取或设置该文本。 3 public virtual bool ShowForDisplay{get;set;} //获取或设置指定的值是否在 UI 中显示模式则应将该模型 (而不只是编辑模式)。 4 public virtual bool ShowForEdit {get;set;} //获取或设置指定的值是否应显示属性编辑模式 (与显示模式)。 5 public virtual string TemplateHint {get;set;} //获取或设置该值指示模板 (数据绑定控件) 应使用 UI 对模型。 6 public virtual string Watermark{get;set;} //获取或设置文本框的水印文本。 7 public object Model { get; set; } //获取或设置属性的值 8 public virtual bool RequestValidationEnabled { get;set;} //获取或设置指定的值请求验证是否启用。 9 public virtual Dictionary<string, object> AdditionalValues{get;set;} //获取包含有关模型的其他元数据的收集。
在这里,可以通过设置模型元数据的各项属性,来完成自己的需求。这只是经常用到的几个,其他我就不一一列举了。在这里,我要介绍一个方便扩展的属性:AdditionalValues,因其为字典类型,所有可以很方便的扩展其他数据属性值,比如,就拿UI的显示长度UILength为例,当然,要创建:IMetadataAware接口。
1 public interface IMetadataAware 2 { 3 // Methods 4 void OnMetadataCreated(ModelMetadata metadata); 5 }
实现接口:
1 public virtual void OnMetadataCreated(ModelMetadata metadata) 2 { 3 metadata.AdditionalValues.Add("UILength", 100); 4 }
那么,如何在前台获取设置的值呢?
1 @ViewData.ModelMetadata.AdditionalValues["UILength"]
除了这个属性,TemplateHint属性用起来也很灵活,指定了其属性值,可以对其指定UI显示模板。
好了,今天就写到这,感觉自己还有很多方面需要提升啊,知道的太少了。