Search code examples
asp.net-mvcunobtrusive-validation

MVC unobtrusive validation - Custom validator that depends on a previous selection


I have a standard address form with a number of fields. e.g.

  • Address line 1
  • Address line 2
  • Country
  • State
  • Postal code

The problem is that the "state" field should be a required field only when "country" is set to USA. If the country is set to anything else, then it should not be required. I could handle it in the controller but I'd like to do it on the client side unobtrusively. Any suggestions?


Solution

  • Just wrote a quick demo for your requirement.

    // model
    public class Address
    {
        public int Id { get; set; }
        public string AddressLine1 { get; set; }
        public string AddressLine2 { get; set; }
    
        [Required]
        public string Country { get; set; }
    
        [RequiredIfCountryIsUSA]
        public string State { get; set; }
        public string PostCode { get; set; }
    }
    
    
    // Validation Attribute
    public class RequiredIfCountryIsUSA : ValidationAttribute, IClientValidatable
    {
        public RequiredIfCountryIsUSA()
        {
    
        }
    
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            var countryPropertyInfo = validationContext.ObjectInstance.GetType().GetProperty("Country");
            var countryValue = countryPropertyInfo.GetValue(validationContext.ObjectInstance, null).ToString();
            if (countryValue == "USA" && (value == null || string.IsNullOrEmpty(value.ToString().Trim())))
            {
                return new ValidationResult("State is required when Country is USA");
            }
    
            return ValidationResult.Success;
        }
    
        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            var rule = new ModelClientValidationRule();
            rule.ErrorMessage = "State is required when country is USA";
            rule.ValidationParameters.Add("country", "USA");
            rule.ValidationType = "iscountryusa";
    
            yield return rule;
        }
    }
    

    client side javascript

    (function ($) {
    $.validator.addMethod("iscountryusa", function (state, element, country) {
        var country = $('#Country').val();
    
        if (country == 'USA' && state == '') {
            return false;
        }
    
        return true;
    });
    
    $.validator.unobtrusive.adapters.addSingleVal("iscountryusa", "country");
    } (jQuery));