2010-01-05 17 views
7

Attualmente sto provando a lavorare con la convalida MVC e sto riscontrando alcuni problemi in cui è richiesto un campo a seconda del valore di un altro campo. Un esempio è sotto (che non ho ancora capito) - Se il PaymentMethod == "Check", dovrebbe essere richiesto il ChequeName, altrimenti può essere lasciato passare.Validazione MVC Asp.Net campi dipendenti

[Required(ErrorMessage = "Payment Method must be selected")] 
public override string PaymentMethod 
{ get; set; } 

[Required(ErrorMessage = "ChequeName is required")] 
public override string ChequeName 
{ get; set; } 

sto usando le System.ComponentModel.DataAnnotations per la [Required], e hanno anche esteso un ValidationAttribute per cercare di ottenere questo lavoro, ma non riesco a passare una variabile attraverso di fare la convalida (estensione di seguito)

public class JEPaymentDetailRequired : ValidationAttribute 
{ 
    public string PaymentSelected { get; set; } 
    public string PaymentType { get; set; } 

    public override bool IsValid(object value) 
    { 
     if (PaymentSelected != PaymentType) 
      return true; 
     var stringDetail = (string) value; 
     if (stringDetail.Length == 0) 
      return false; 
     return true; 
    } 
} 

Implementazione:

[JEPaymentDetailRequired(PaymentSelected = PaymentMethod, PaymentType = "Cheque", ErrorMessage = "Cheque name must be completed when payment type of cheque")] 

qualcuno ha avuto esperienza con questo tipo di convalida? Sarebbe stato meglio scriverlo nel controller?

Grazie per il vostro aiuto.

+0

Ripensandoci ... Come si può impostare il pagamento selezionato = Metodo di pagamento? Dovresti ricevere un errore perché PaymentMethod non è un'espressione costante. – Min

+0

Ciao Min, hai ragione. Ho pensato che potrei essere in grado di farlo in questo modo ma non funziona. Volevo solo mostrare ciò che avevo provato, ma ho anche commentato che non mi avrebbe permesso di passare attraverso la variabile. –

risposta

3

Scriverò la logica di convalida nel modello, non nel controller. Il controller deve gestire solo l'interazione tra la vista e il modello. Dal momento che è il modello che richiede la convalida, penso che sia ampiamente considerato come il luogo per la logica della convalida.

Per la convalida che dipende dal valore di un'altra proprietà o campo, io (sfortunatamente) non vedo come evitare completamente la scrittura di un codice per quello nel modello, come mostrato nel libro MVC Wrox ASP.NET, del tipo:

public bool IsValid 
{ 
    get 
    { 
    SetRuleViolations(); 
    return (RuleViolations.Count == 0); 
    } 
} 

public void SetRuleViolations() 
{ 
    if (this.PaymentMethod == "Cheque" && String.IsNullOrEmpty(this.ChequeName)) 
    { 
    RuleViolations.Add("Cheque name is required", "ChequeName"); 
    } 
} 

Fare tutte le convalide in modo dichiarativo sarebbe grandioso. Sono sicuro che potresti creare un RequiredDependentAttribute, ma che gestirà solo questo tipo di logica. Cose che sono anche leggermente più complesse richiederebbero un altro attributo piuttosto specifico, ecc. Che diventa rapidamente pazzo.

+0

grazie djuth, ho preso un ModelStateDictionary e fatto convalida con questo nel modello, e poi passato il dizionario al controller per unirmi a ModelState. Sembra fare il trucco e mi permette di fare un po 'di lavoro programmatico - non è così bello solo facendo una dichiarazione per attributo, ma almeno posso ottenere tutto in un unico punto. Non sei sicuro di come andrà se ci sarà più di un errore per attributo. –

2

Il problema può essere risolto in modo relativamente semplice mediante l'utilizzo di conditional validation attribute ad es.

[RequiredIf("PaymentMethod == 'Cheque'")] 
public string ChequeName { get; set; } 
4

Se volete cliente validazione lato oltre al modello di validazione sul server, penso che il modo migliore per andare è un attributo di convalida personalizzato (come Jaroslaw suggerito). Sto includendo la fonte qui di quello che uso.

attributo personalizzato:

public class RequiredIfAttribute : DependentPropertyAttribute 
{ 
    private readonly RequiredAttribute innerAttribute = new RequiredAttribute(); 

    public object TargetValue { get; set; } 


    public RequiredIfAttribute(string dependentProperty, object targetValue) : base(dependentProperty) 
    { 
     TargetValue = targetValue; 
    } 


    protected override ValidationResult IsValid(object value, ValidationContext validationContext) 
    { 
     // get a reference to the property this validation depends upon 
     var containerType = validationContext.ObjectInstance.GetType(); 
     var field = containerType.GetProperty(DependentProperty); 

     if (field != null) 
     { 
      // get the value of the dependent property 
      var dependentvalue = field.GetValue(validationContext.ObjectInstance, null); 

      // compare the value against the target value 
      if ((dependentvalue == null && TargetValue == null) || 
       (dependentvalue != null && dependentvalue.Equals(TargetValue))) 
      { 
       // match => means we should try validating this field 
       if (!innerAttribute.IsValid(value)) 
        // validation failed - return an error 
        return new ValidationResult(ErrorMessage, new[] { validationContext.MemberName }); 
      } 
     } 

     return ValidationResult.Success; 
    } 

    public override IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) 
    { 
     var rule = new ModelClientValidationRule 
         { 
          ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()), 
          ValidationType = "requiredif" 
         }; 

     var depProp = BuildDependentPropertyId(DependentProperty, metadata, context as ViewContext); 

     // find the value on the control we depend on; 
     // if it's a bool, format it javascript style 
     // (the default is True or False!) 
     var targetValue = (TargetValue ?? "").ToString(); 
     if (TargetValue != null) 
      if (TargetValue is bool) 
       targetValue = targetValue.ToLower(); 

     rule.ValidationParameters.Add("dependentproperty", depProp); 
     rule.ValidationParameters.Add("targetvalue", targetValue); 

     yield return rule; 
    } 
} 

Jquery estensione convalida:

$.validator.unobtrusive.adapters.add('requiredif', ['dependentproperty', 'targetvalue'], function (options) { 
    options.rules['requiredif'] = { 
     dependentproperty: options.params['dependentproperty'], 
     targetvalue: options.params['targetvalue'] 
    }; 
    options.messages['requiredif'] = options.message; 
}); 

$.validator.addMethod('requiredif', 
    function (value, element, parameters) { 
     var id = '#' + parameters['dependentproperty']; 

     // get the target value (as a string, 
     // as that's what actual value will be) 
     var targetvalue = parameters['targetvalue']; 
     targetvalue = (targetvalue == null ? '' : targetvalue).toString(); 

     // get the actual value of the target control 
     var actualvalue = getControlValue(id); 

     // if the condition is true, reuse the existing 
     // required field validator functionality 
     if (targetvalue === actualvalue) { 
      return $.validator.methods.required.call(this, value, element, parameters); 
     } 

     return true; 
    } 
); 

Decorare una proprietà con l'attributo:

[Required] 
public bool IsEmailGiftCertificate { get; set; } 

[RequiredIf("IsEmailGiftCertificate", true, ErrorMessage = "Please provide Your Email.")] 
public string YourEmail { get; set; } 
+0

Mi rendo conto che questa risposta ha 2 anni ma sto cercando di farlo funzionare e fondamentalmente si attiva la convalida sulla proprietà dipendente indipendentemente dal valore della prima proprietà. Qualsiasi aiuto sarebbe apprezzato. –

3

basta usare la convalida biblioteca infallibile che è disponibile su CodePlex : https://foolproof.codeplex.com/

Supporta i seguenti attributi di validazione "requiredif"/decorazioni:

[RequiredIf] 
[RequiredIfNot] 
[RequiredIfTrue] 
[RequiredIfFalse] 
[RequiredIfEmpty] 
[RequiredIfNotEmpty] 
[RequiredIfRegExMatch] 
[RequiredIfNotRegExMatch] 

per iniziare è facile:

  1. scaricare il pacchetto dal link fornito
  2. Aggiungere un riferimento alla file .dll incluso
  3. Importare i file javascript inclusi
  4. Verificare che il proprio vi ews fa riferimento ai file javascript inclusi all'interno del relativo codice HTML per la convalida non invasiva di javascript e jquery.
Problemi correlati