自定义DataAnnotationsModelMetadataProvider无法正常工作
我有许多属性需要一个或多个validation属性,如下所示:
public class TestModel { [Some] [StringLength(6)] [CustomRequired] // more attributes... public string Truck { get; set; } }
请注意以上所有注释都有效。
我不想一直写这个,因为每当应用Some
时,所有其他属性也会应用于属性。 我希望能够做到这一点:
public class TestModel { [Some] public string Truck { get; set; } }
现在这可以通过inheritance来实现; 因此,我编写了一个自定义DataAnnotationsModelMetadataProvider
并覆盖了CreateMetadata
。 这会查找使用Some
修饰的任何内容,然后为其添加更多属性:
public class TruckNumberMetadataProvider : DataAnnotationsModelMetadataProvider { protected override ModelMetadata CreateMetadata(IEnumerable attributes, Type containerType, Func modelAccessor, Type modelType, string propertyName) { var attributeList = attributes.ToList(); if (attributeList.OfType().Any()) { attributeList.Add(new StringLengthAttribute(6)); attributeList.Add(new CustomRequiredAttribute()); } return base.CreateMetadata(attributeList, containerType, modelAccessor, modelType, propertyName); } }
这些属性有助于:
public class CustomRequiredAttribute : RequiredAttribute { public CustomRequiredAttribute() { this.ErrorMessage = "Required"; } } public class SomeAttribute : RegularExpressionAttribute { public SomeAttribute() : base(@"^[1-9]d{0,5}$") { } }
用法
@Html.TextBoxFor(x => x.Truck)
HTML呈现:
问题/问题
-
CustomRequired
已应用。 但是,如果我使用CustomRequired
,它为什么会从基类RequiredAttribute
获取消息。data-val-required
应该只说必需 。 - 不应用6个字符串的
StringLenth
。StringLength
没有任何渲染迹象,为什么?
您的自定义DataAnnotationsModelMetadataProvider
正在做的是创建/修改与您的属性关联的ModelMetada
。
如果检查ModelMetadata类,您将注意到它包含诸如string DisplayName
和string DisplayFormatString
类的属性,这些属性是根据[Display]
和[DisplayFormat]
属性的应用程序设置的。 它还包含一个bool IsRequired
属性,用于确定是否需要属性的值(稍后再说一点)。
它不包含与正则表达式或最大长度相关的任何内容,或者实际上与validation相关的任何内容(除了IsRequired
属性和用于validation值可以转换为type
的ModelType
之外)。
HtmlHelper
方法负责生成传递给视图的html。 要生成data-val-*
属性, TextBoxFor()
方法在内部调用HtmlHelper
类的GetUnobtrusiveValidationAttributes()
方法,该方法又调用DataAnnotationsModelValidatorProvider
类中的方法,该方法最终生成data-val
属性名称和使用的值的Dictionary
。生成HTML。
如果您需要更多细节(请参阅下面的链接),我将留给您探索源代码,但总结一下,它会获取应用于您的Truck
属性的所有属性的集合,这些属性inheritance自ValidationAttribute
以构建字典。 在您的情况下,唯一的ValidationAttribute
是[Some]
,它派生自RegularExpressionAttribute
因此添加了data-val-regex
和data-val-regex-pattern
属性。
但是因为您已在TruckNumberMetadataProvider
添加了CustomRequiredAttribute
,所以TruckNumberMetadataProvider
的IsRequired
属性已设置为true
。 如果您使用DataAnnotationsModelValidatorProvider
的GetValidators()
,您将看到RequiredAttribute
会自动添加到属性集合中,因为您尚未将属性应用于该属性。 相关的代码片段是
if (AddImplicitRequiredAttributeForValueTypes && metadata.IsRequired && !attributes.Any(a => a is RequiredAttribute)) { attributes = attributes.Concat(new[] { new RequiredAttribute() }); }
这导致data-val-required
属性被添加到html中(它使用默认消息,因为它对CustomRequiredAttribute
一无所知)
如果您想了解内部工作原理,可以使用源代码文件
- HtmlHelper.cs – 在第413行引用
GetUnobtrusiveValidationAttributes()
方法 - ModelValidatorProviders.cs – 获取用于validation的各种ValidatorProviders
- DataAnnotationsModelValidatorProvider.cs –
ValidationAttributes
的ValidatorProvider
一个可能的解决方案是,如果您真的只想使用一个ValidationAttribute
就是让它实现IClientValidatable
并在GetClientValidationRules()
方法中添加规则,例如
var rule = new ModelClientValidationRule { ValidationType = "required", ErrorMessage = "Required" }
它将由ClientDataTypeModelValidatorProvider
读取(并删除您的TruckNumberMetadataProvider
类)。 但是,这会产生维护噩梦,因此我建议您只需将3个validation属性添加到您的属性中
上述就是C#学习教程:自定义DataAnnotationsModelMetadataProvider无法正常工作分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/942271.html