C# 自定义DataAnnotationsModelMetadataProvider不工作
我有许多属性需要1个或多个验证属性,如下所示:C# 自定义DataAnnotationsModelMetadataProvider不工作,c#,asp.net-mvc,razor,asp.net-mvc-5,C#,Asp.net Mvc,Razor,Asp.net Mvc 5,我有许多属性需要1个或多个验证属性,如下所示: public class TestModel { [Some] [StringLength(6)] [CustomRequired] // more attributes... public string Truck { get; set; } } 请注意以上所有注释都是有效的 我不想一直这样写,因为每当应用Some时,所有其他属性也应用于属性。我希望能够做到这一点: public class TestModel
public class TestModel
{
[Some]
[StringLength(6)]
[CustomRequired] // more attributes...
public string Truck { get; set; }
}
请注意以上所有注释都是有效的
我不想一直这样写,因为每当应用Some
时,所有其他属性也应用于属性。我希望能够做到这一点:
public class TestModel
{
[Some]
public string Truck { get; set; }
}
现在这是可以继承的;因此,我编写了一个自定义的DataAnnotationsModelMetadataProvider
,并重写了CreateMetadata
。这将查找用Some
修饰的任何内容,然后向其添加更多属性:
public class TruckNumberMetadataProvider : DataAnnotationsModelMetadataProvider
{
protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
{
var attributeList = attributes.ToList();
if (attributeList.OfType<SomeAttribute>().Any())
{
attributeList.Add(new StringLengthAttribute(6));
attributeList.Add(new CustomRequiredAttribute());
}
return base.CreateMetadata(attributeList, containerType, modelAccessor, modelType, propertyName);
}
}
用法
@Html.TextBoxFor(x => x.Truck)
呈现的HTML:
<input name="Truck" id="Truck" type="text" value=""
data-val-required="The Truck field is required."
data-val-regex-pattern="^[1-9]\d{0,5}$"
data-val-regex="The field Truck must match the regular expression '^[1-9]\d{0,5}$'."
data-val="true">
</input>
问题/问题
CustomRequired
。但是,如果我使用的是CustomRequired
,为什么它会从基类RequiredAttribute
中提取消息呢。数据值required
应该只说requiredStringLenth
。没有为StringLength
呈现任何内容的迹象,为什么自定义的
DataAnnotationsModelMetadataProvider
正在创建/修改与属性关联的ModelMetada
如果检查该类,您会注意到它包含的属性,如string DisplayName
和string DisplayFormatString
,这些属性是根据[Display]
和[DisplayFormat]
属性的应用程序设置的。它还包含一个boolisrequired
属性,用于确定是否需要属性值(稍后将对此进行详细说明)
它不包含任何与正则表达式或最大长度相关的内容,也不包含任何与验证相关的内容(除了IsRequired
属性和ModelType
,后者用于验证值是否可以转换为类型
)
负责生成传递给视图的html的是HtmlHelper
方法。要生成data val-*
属性,您的TextBoxFor()
方法在内部调用GetUnobtrusiveValidationAttributes()
HtmlHelper类的方法,该方法依次调用DataAnnotationsModelValidatorProvider
类中的方法,这些方法最终生成数据val
属性名称和值的字典
如果您想了解更多详细信息(请参阅下面的链接),我将让您自行探索源代码,但总而言之,它将获得应用于Truck
属性的所有属性的集合,这些属性继承自ValidationAttribute
,以构建字典。在您的案例中,唯一的ValidationAttribute
是[Some]
,它派生自RegularExpressionAttribute
,因此添加了data val regex
和data val regex模式
属性
但是,由于您已在TruckNumberMetadata提供程序中添加了CustomRequiredAttribute
,因此模型元数据的IsRequired
属性已设置为true
。如果使用DataAnnotationsModelValidatorProvider
的GetValidators()
,您将看到RequiredAttribute
会自动添加到属性集合中,因为您尚未将其应用于属性。相关的代码片段是
if (AddImplicitRequiredAttributeForValueTypes && metadata.IsRequired && !attributes.Any(a => a is RequiredAttribute))
{
attributes = attributes.Concat(new[] { new RequiredAttribute() });
}
这导致将数据val required
属性添加到html中(它使用默认消息,因为它不知道您的CustomRequiredAttribute
)
如果您想了解内部工作,可以使用源代码文件开始
-请参阅第413行的方法
-获取用于验证的各种验证器提供程序
-验证属性的验证提供程序ValidationAttributes
如果您真的只想使用一个ValidationAttribute
,一个可能的解决方案是让它实现IClientValidatable
,例如,在GetClientValidationRules()
方法中添加规则
var rule = new ModelClientValidationRule
{
ValidationType = "required",
ErrorMessage = "Required"
}
将由ClientDataTypeModelValidatorProvider
读取(并删除您的TruckNumberMetadataProvider
类)。但是,这会造成维护噩梦,因此我建议您只需将3个验证属性添加到您的属性中关于(1),您是否已在global.asax.cs
中注册自定义属性?@StephenMuecke是的,我已注册它们。当我直接在我的模型上使用它们时,它们就起作用了。您可以实际获取代码,它将重现问题。我没有对模型应用必需的,因此它肯定是从自定义提供商处获取的,但由于某些原因,错误消息未被获取。这有帮助,我将在周末后进行调查。谢谢
var rule = new ModelClientValidationRule
{
ValidationType = "required",
ErrorMessage = "Required"
}