RequiredAttribute z AllowEmptyString = true w ASP.NET MVC 3 unobtrusive validation

Jeśli mam [Required(AllowEmptyStrings = true)] deklaracja w moim modelu widoku, Walidacja jest zawsze uruchamiana przy pustych wejściach. Znalazłem Artykuł który wyjaśnia dlaczego tak się dzieje. Czy wiesz, czy jest dostępna poprawka? Jeśli nie, to jak sobie z tym radzisz?

Author: UserControl, 2011-06-22

2 answers

Uwaga: zakładam, że masz AllowEmptyStrings = true, ponieważ używasz modelu widoku poza scenariuszem sieciowym; w przeciwnym razie nie wydaje się, aby wymagane atrybuty zezwalały na puste ciągi w scenariuszu sieciowym.

Istnieją trzy kroki, aby sobie z tym poradzić:

  1. Tworzenie niestandardowego adaptera atrybutów, który dodaje parametr walidacji
  2. zarejestruj swój adapter jako fabrykę adapterów
  3. Override jQuery Funkcja walidacji pozwalająca na puste ciągi znaków, gdy ten atrybut jest obecny

Krok 1: Niestandardowy adapter atrybutów

Zmodyfikowałem RequiredAttributeAdapter, aby dodać w tej logice:

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 };
        }
    }
}

Punkt 2. Zarejestruj to w swoim global.asax / Application_Start()

    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);
    }

Punkt 3. Override the jQuery "required" validation function

Odbywa się to za pomocą jQuery.walidator.wywołanie addMethod (), dodając naszą niestandardową logikę, a następnie wywołanie oryginalnej funkcji - więcej o tym podejściu przeczytasz tutaj . Jeśli używasz tego w całej witrynie, być może w pliku skryptu, do którego odwołujesz się z _Layout.cshtml. Oto przykładowy blok skryptów, który możesz wrzucić na stronę w celu przetestowania:

<script>
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
);
</script>
 22
Author: Jon Galloway,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-14 23:29:52

Zamiast dekorować wartość atrybutem "Required", używam poniższego. Uważam, że jest to najprostsze rozwiązanie tej kwestii.

[DisplayFormat (ConvertEmptyStringToNull=false)]

 15
Author: Rick Arthur,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-09 07:02:42