Search code examples
c#asp.netasp.net-mvcvalidationrequiredfieldvalidator

ASP.NET MVC. How disable required validation based on a parameter?


I do have a entity class with some required attributes depending of a selector.

For instance: The Selector can assume "1" or "2". If selector was "1", a group of parameters shall be required. If selector is "2" another set of parameters is required.

class MyClass{

    public int Selector {get;set;} // 1 or 2

    public string A_required_for_1 {get;set;}
    public string B_required_for_1 {get;set;}

    public string C_required_for_2 {get;set;}
    public string D_required_for_2 {get;set;}

    public string E_Required_for_both_selectors {get;set;}

}

User should be able to switch between selectors during Create or Edit actions in view.

Client validation is already solved.

How can I deal with it in server validation?


Solution

  • You can either create your own custom validation attribute or use MVC Foolproof Validation and then do:

    class MyClass
    {
    
        public int Selector {get;set;} // 1 or 2
    
        [RequiredIf("Selector == 1", ErrorMessage = "Your Error Message")]
        public string A_required_for_1 {get;set;}
    
        [RequiredIf("Selector == 1", ErrorMessage = "Your Error Message")]
        public string B_required_for_1 {get;set;}
    
        [RequiredIf("Selector == 2", ErrorMessage = "Your Error Message")]
        public string C_required_for_2 {get;set;}
    
        [RequiredIf("Selector == 2", ErrorMessage = "Your Error Message")]
        public string D_required_for_2 {get;set;}
    
        [Required("Your Error Message")]
        public string E_Required_for_both_selectors {get;set;}
    
     }
    

    As mentioned by Win it does not seem to have been in active development for a while so you may want to go down the route of creating your own custom validation attribute, which does require more work but you can have a finer control over the validation itself. Choose depending on your needs.

    For a custom validation attribute you could do something like this:

    public class RequiredIfOtherProperty : ValidationAttribute
    {
        private readonly string _otherPropertyName;
        private readonly string _compareValue;
    
        public RequiredIfOtherProperty(string otherPropertyName, string compareValue)
        {
            _otherPropertyName = otherPropertyName;
            _compareValue = compareValue;
        }
    
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            var otherProperty = validationContext.ObjectType.GetProperty(_otherPropertyName);
            if (otherProperty == null)
            {
                return new ValidationResult($"Property '{_otherPropertyName}' does not exist");
            );
    
            var otherPropertyValue = otherProperty.GetValue(validationContext.ObjectInstance, null);
            if (!_compareValue.Equals(otherPropertyValue))
            {
                return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName));
            }
    
            return null;
        }
    }
    

    It should give you a rough idea on what you can do and you can change the actual validation to however you like. You can then use it like a normal attribute e.g.

    [RequiredIfOtherProperty("SomeProperty", "ValueToCompareWith")]