ASP.NET MVC Dependent Asphalt Fields

I'm currently trying to work with MVC validation and run into some problems when a field is required depending on the value of another field. Below is an example (which I haven't figured out yet). If PaymentMethod == "Check", then the name ChequeName is required, otherwise it can be skipped.

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

I am using System.ComponentModel.DataAnnotations for [Required], and have also expanded ValidationAttribute to try to get this working, but I cannot pass a variable to perform validation (extension below)

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

Implementation:

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

Does anyone have experience with this kind of verification? Would it be better to write it to the controller?

Thank you for your help.

+7
validation asp.net-mvc
source share
4 answers

I would write verification logic in the model, not the controller. The controller must handle the interaction between the view and the model. Since this is a model that requires verification, I believe that it is widely regarded as a place for verification logic.

To check, which depends on the value of another property or field, I (unfortunately) do not see how to completely avoid writing code for this in the model, for example, shown in the Wrox ASP.NET MVC book, sort like:

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

Performing the entire check declaratively would be wonderful. I'm sure you can do RequiredDependentAttribute , but this will only work with one type of logic. Material that is even a little more complicated will require another rather specific attribute, etc., which quickly goes crazy.

+3
source share

If you need client-side validation in addition to validating the model on the server, I think the best way is to have a custom validation attribute (like suggested by Jaroslaw). I am including the source here of the one I am using.

User attribute:

 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 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 validation extension:

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

Decorating a property with an attribute:

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

Just use the Foolproof authentication library available in Codeplex: https://foolproof.codeplex.com/

It supports the following attributes / attributes of the "requiredif" attribute:

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

Easy to start:

  • Download the package from the link provided
  • Add a link to the .dll file.
  • Import included javascript files
  • Make sure your views reference the included javascript files from your HTML code for unobtrusive javascript and jquery validation.
+3
source share

Your problem can be solved relatively simply using a conditional validation attribute , for example.

 [RequiredIf("PaymentMethod == 'Cheque'")] public string ChequeName { get; set; } 
+2
source share

All Articles