risposta

21

Nota: suppongo che tu abbia AllowEmptyStrings = true perché stai anche utilizzando il tuo modello di visualizzazione al di fuori di uno scenario web; altrimenti non sembra che ci sia molto di un punto per avere un attributo obbligatorio che consente stringhe vuote in uno scenario web.

ci sono tre passi per gestire questo:

  1. Creare un adattatore attributo personalizzato che aggiunge che il parametro di convalida
  2. Pubblica il tuo adattatore come una fabbrica adattatore
  3. Override jQuery Validation funzione per consentire vuoto stringhe quando questo attributo è presente

Passaggio 1: l'adattatore di attributo personalizzato

ho modificato il RequiredAttributeAdapter di aggiungere in questa logica:

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

Passaggio 2. Registra questo nel tuo 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); 
    } 

Fase 3. Override jQuery "required" validation function

Questa operazione viene eseguita utilizzando la chiamata jQuery.validator.addMethod(), aggiungendo la nostra logica personalizzata e quindi chiamando la funzione originale: è possibile leggere ulteriori informazioni su questo approccio here. Se stai usando questo nel tuo sito, forse in un file di script a cui fa riferimento il tuo _Layout.cshtml. Ecco un blocco di script di esempio si può cadere in una pagina di prova:

<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

Grazie per i vostri sforzi, Jon! Sfortunatamente non funziona per me, continuo a vedere il messaggio "field is required" :(Ho verificato che il tuo codice sia eseguito con i debugger VS e browser e non ho script personalizzati o codice relativo alla validazione che potrebbe interferire. jQuery 1.4.1 Può essere questo il problema? – UserControl

+0

E sì, hai ragione che ho bisogno della funzionalità al di fuori degli scenari web (il mio livello di servizio applicativo esegue controlli di convalida simili per essere DRY). – UserControl

+0

+1 Questo sembra essere un bella soluzione, mi chiedo perché non funzioni, ma forse potresti semplificarla, se non restituisci alcuna regola di validazione (array vuoto) nell'adattatore in caso di AllowEmptyStrings. Potresti quindi risparmiare la magia del lato client. controlla se l'attributo richiesto è stato omesso correttamente nel tuo input. Se ancora non funziona, dovresti eseguire il debug del codice dell'adattatore e vedere se viene chiamato in modo appropriato (se la registrazione è ok). –

15

Invece di decorare il valore con l'attributo 'richiesto', io uso il seguente. Trovo che sia la soluzione più semplice a questo problema.

[DisplayFormat (ConvertEmptyStringToNull = false)]

+0

Sono d'accordo - questo sembra essere il modo più semplice per affrontare questo. Se si desidera consentire stringhe vuote, è sufficiente modificare il valore null in "" nel controller prima di salvare! –

+2

Bello! Questo richiamo di [Required] mi ha infastidito per anni su più siti Web asp.net. (Ora sto usando entrambi [Required (AllowEmptyStrings = true), DisplayFormat (ConvertEmptyStringToNull = false)] e funziona benissimo –

+0

Ottima risposta. Grazie mille –