Odpowiedz

21

Uwaga: Zakładam, że masz AllowEmptyStrings = true, ponieważ używasz również modelu widoku poza scenariuszem sieciowym; w przeciwnym razie nie wydaje się, aby było dużo sensu posiadanie wymaganego atrybutu, który zezwala na puste ciągi w scenariuszu internetowym.

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

  1. Tworzenie adapter niestandardowy atrybut, który dodaje, że parametr walidacji
  2. Zarejestruj swoją kartę jako fabryki adaptera
  3. przesłonić jQuery Validation funkcjonować w celu umożliwienia pusty ciągi, gdy atrybut ten jest obecny

Krok 1: niestandardowy adapter atrybutów

zmodyfikowałem RequiredAttributeAdapter do dodania w tej logiki:

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

Krok 2. Rejestr ten 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); 
    } 

Krok 3. Zastąp jQuery "wymagana" funkcja sprawdzania poprawności

Odbywa się to za pomocą wywołania jQuery.validator.addMethod(), dodając naszą niestandardową logikę, a następnie wywołując oryginalną funkcję - możesz przeczytać więcej o tym podejściu here. Jeśli używasz tego w swojej witrynie, być może w pliku skryptowym wymienionym w twoim _Layout.cshtml. Oto blok przykładowy skrypt można upuścić na stronie do testu:

<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> 
+0

Dzięki za starania, Jon! Niestety nie działa to dla mnie, wciąż widzę komunikat "pole jest wymagane" :(Sprawdziłem dwukrotnie, czy twój kod jest wykonywany z VS i debuggery przeglądarki i nie mam żadnych niestandardowych skryptów lub kodu związanego z walidacją, które mogłyby przeszkadzać. jQuery 1.4.1 Czy to może być problem? – UserControl

+0

I tak, masz rację, że potrzebuję tej funkcji poza scenariuszami sieci (moja warstwa usługi aplikacji wykonuje podobne testy sprawdzania poprawności, aby być DRY) – UserControl

+0

+1 To wydaje się być fajne rozwiązanie, zastanawiam się, dlaczego to nie działa.Ale może można go uprościć, jeśli nie zwróci żadnej zasady sprawdzania poprawności (pusta tablica) w adapterze w przypadku AllowEmptyStrings.Możesz następnie oszczędzić magii po stronie klienta.Możesz następnie łatwo sprawdź czy wymagany atrybut jest poprawnie pominięty na twoim wejściu.Jeśli nadal nie działa, powinieneś debugować kod adaptera i sprawdzić, czy jest on odpowiednio nazwany (jeśli rejestracja jest OK). –

15

Zamiast dekoracji wartość za pomocą atrybutu „wymagane”, używam następujące. Uważam, że jest to najprostsze rozwiązanie tego problemu.

[DisplayFormat (ConvertEmptyStringToNull = false)]

+0

Zgadzam się - wydaje się to najłatwiejszym sposobem na rozwiązanie tego problemu. Jeśli chcesz zezwolić na puste ciągi, po prostu zmień zerową wartość null na "" w kontrolerze przed zapisaniem! –

+2

Piękne! To cofnięcie [Wymagane] drażniło mnie od lat na wielu stronach asp.net (teraz używam obu [Wymagane (AllowEmptyStrings = true), DisplayFormat (ConvertEmptyStringToNull = false)] i to działa świetnie –

+0

Świetna odpowiedź. Bardzo dziękuję –

Powiązane problemy