Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 自定义DataAnnotationsModelMetadataProvider不工作_C#_Asp.net Mvc_Razor_Asp.net Mvc 5 - Fatal编程技术网

C# 自定义DataAnnotationsModelMetadataProvider不工作

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

我有许多属性需要1个或多个验证属性,如下所示:

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
    应该只说required
  • 未应用6个字符的
    StringLenth
    。没有为
    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"
    }