在ASP.NET MVC 3中,AllowEmptyString = true的RequiredAttribute

RequiredAttribute with AllowEmptyString=true in ASP.NET MVC 3 unobtrusive validation

如果我的视图模型中有[Required(AllowEmptyStrings = true)]声明,则始终在空输入上触发验证。 我找到了解释其发生原因的文章。 您知道是否有可用的修复程序吗? 如果没有,您将如何处理?


注意:我假设您具有AllowEmptyStrings = true,因为您还在Web场景之外使用视图模型。否则,在Web场景中拥有一个Required属性允许空字符串似乎没有多大意义。

有以下三个步骤可解决此问题:

  • 创建一个自定义属性适配器,添加该验证参数
  • 将适配器注册为适配器工厂
  • 覆盖jQuery Validation函数,以在存在该属性时允许空字符串
  • 步骤1:自定义属性适配器

    我修改了RequiredAttributeAdapter以添加该逻辑:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.Web.Mvc;

    namespace CustomAttributes
    {
        /// <summary>Provides an adapter for the <see cref="T:System.Runtime.CompilerServices.RequiredAttributeAttribute" /> attribute.</summary>
        public class RequiredAttributeAdapter : DataAnnotationsModelValidator<RequiredAttribute>
        {
            /// <summary>Initializes a new instance of the <see cref="T:System.Runtime.CompilerServices.RequiredAttributeAttribute" /> class.</summary>
            /// <param name="metadata">The model metadata.</param>
            /// <param name="context">The controller context.</param>
            /// <param name="attribute">The required attribute.</param>
            public RequiredAttributeAdapter(ModelMetadata metadata, ControllerContext context, RequiredAttribute attribute)
                : base(metadata, context, attribute)
            {
            }
            /// <summary>Gets a list of required-value client validation rules.</summary>
            /// <returns>A list of required-value client validation rules.</returns>
            public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
            {
                var rule = new ModelClientValidationRequiredRule(base.ErrorMessage);
                if (base.Attribute.AllowEmptyStrings)
                {
                    //setting"true" rather than bool true which is serialized as"True"
                    rule.ValidationParameters["allowempty"] ="true";
                }

                return new ModelClientValidationRequiredRule[] { rule };
            }
        }
    }

    步骤2.在您的global.asax / Application_Start()中注册

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            DataAnnotationsModelValidatorProvider.RegisterAdapterFactory(typeof(RequiredAttribute),
              (metadata, controllerContext, attribute) => new CustomAttributes.RequiredAttributeAdapter(metadata,
                controllerContext, (RequiredAttribute)attribute));

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);
        }

    步骤3.重写jQuery"必需"验证功能

    使用jQuery.validator.addMethod()调用完成此操作,添加我们的自定义逻辑,然后调用原始函数-您可以在此处了解有关此方法的更多信息。如果您在整个站点中都使用此功能,则可能在_Layout.cshtml引用的脚本文件中。这是一个示例脚本块,您可以在页面中进行测试:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    jQuery.validator.methods.oldRequired = jQuery.validator.methods.required;

    jQuery.validator.addMethod("required", function (value, element, param) {
        if ($(element).attr('data-val-required-allowempty') == 'true') {
            return true;
        }
        return jQuery.validator.methods.oldRequired.call(this, value, element, param);
    },
    jQuery.validator.messages.required // use default message
    );


    我不是使用'Required'属性来修饰值,而是使用以下内容。我发现它是解决此问题的最简单方法。

    [DisplayFormat(ConvertEmptyStringToNull=false)]