2010-01-05 7 views
7

Ich versuche derzeit MVC Validierung zu arbeiten, und stoße auf einige Probleme, wo ein Feld abhängig von dem Wert eines anderen Feldes erforderlich ist. Ein Beispiel ist unten (das habe ich noch nicht herausgefunden) - Wenn der PaymentMethod == "Check", dann sollte der ChequeName erforderlich sein, sonst kann es durchgelassen werden.Asp.Net MVC Validation - abhängige Felder

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

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

Ich benutze die System.ComponentModel.DataAnnotations für die [Erforderlich], und haben erweitert auch ein Validation diese Funktion zu versuchen und zu erhalten, aber ich kann nicht eine Variable übergeben durch die Validierung zu tun (Erweiterung unten)

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

Umsetzung:

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

hat jemand schon Erfahrung mit dieser Art von Prüfung? Wäre es nur besser, es in den Controller zu schreiben?

Danke für Ihre Hilfe.

+0

Auf den zweiten Gedanken ... Wie können Sie die PaymentSelected = PaymentMethod? Sie sollten einen Fehler erhalten, da PaymentMethod kein konstanter Ausdruck ist. – Min

+0

Hallo Min, du hast Recht. Ich dachte, dass ich es vielleicht so machen könnte, aber es funktioniert nicht. Ich wollte nur zeigen, was ich versucht hatte, aber auch kommentieren, dass es mir nicht erlaubte, die Variable zu passieren. –

Antwort

3

Ich würde die Validierungslogik in das Modell schreiben, nicht den Controller. Der Controller sollte nur die Interaktion zwischen der Ansicht und dem Modell handhaben. Da es das Modell ist, das Validierung erfordert, denke ich, dass es weithin als der Ort für die Validierungslogik angesehen wird.

Für die Validierung, die von dem Wert einer anderen Eigenschaft oder Feld abhängt, ich (leider) nicht sehen, wie vollständig das Schreiben von Code für das im Modell zu vermeiden, wie im Wrox ASP.NET MVC Buch gezeigt, Art von wie:

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

Alle Validierung würde deklarativ wäre großartig. Ich bin sicher, dass Sie eine RequiredDependentAttribute machen könnten, aber das würde nur diese eine Art von Logik behandeln. Zeug, das sogar etwas komplexer ist, würde ein weiteres hübsches spezifisches Attribut usw. erfordern, das schnell verrückt wird.

+0

danke djuth, ich habe ein ModelStateDictionary genommen und die Validierung mit diesem im Modell durchgeführt und dann das Wörterbuch an den Controller zurückgegeben, um es in den ModelState einzufügen. Scheint, den Trick zu machen und erlaubt mir, einige programmatische Arbeit zu machen - nicht ganz so nett, nur eine Deklaration pro Attribut zu machen, aber wenigstens kann ich alles an einem Punkt bekommen. Nicht sicher, wie das geht, wenn es mehr als einen Fehler pro Attribut tho gibt. –

4

Wenn Sie Client-seitige Validierung zusätzlich wollen die Validierung auf dem Server zu modellieren, ich denke, der beste Weg, eine benutzerdefinierte Validierung Attribut zu gehen (wie Jaroslaw vorgeschlagen). Ich schließe hier die Quelle ein, die ich verwende.

Benutzerdefinierte Attribut:

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 Validierung Erweiterung:

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

eine Eigenschaft mit dem Attribut Dekorieren:

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

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

Ich weiß, dass diese Antwort 2 Jahre alt ist, aber ich versuche, dies zur Arbeit zu bringen und im Grunde feuert es die Validierung der abhängigen Eigenschaft, egal was der Wert der ersten Eigenschaft ist. Jede Hilfe wäre willkommen. –

3

einfach die harmlose Validierung Bibliothek verwenden, die auf Codeplex verfügbar : https://foolproof.codeplex.com/

Es unterstützt die folgenden "requiredif" Validierung Attribute/Dekorationen:

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

begann zu bekommen, ist einfach:

  1. das Paket aus dem bereitgestellten Link hinzufügen zu der
  2. herunterladen Referenz enthaltene .dll-Datei
  3. Importieren Sie die enthaltenen Javascript-Dateien
  4. Stellen Sie sicher, dass Ihr vi ews verweist auf die enthaltenen JavaScript-Dateien aus seinem HTML-Code für unauffällige JavaScript- und Jquery-Validierung.