ASP.Net MVC : Conditional Validation using ValidationAttribute

In ASP.Net MVC we can validate each input field by decorating the corresponding property in the model class with some validation attributes like Required, MaxLength, MinLength,...etc.

Sometime we need to validate a property according to another property value for example if we have a registration form and we need the user enter his age if he is a male and age not required if the user sex is female. So if we decorated the Age property with Required attribute it will show error message even if the user is female, so we need to bypass this check with females.

Assume our registration form will contains three fields, name, sex and age, and its model will be as follows
public class RegisterationModel
{
    [Required(ErrorMessage = "*")]
    public String Name { get; set; }

    [Required(ErrorMessage = "*")]
    [Display(Name = "Gender")]
    public Sex Sex { get; set; }

    [RequiredIf("Sex", Sex.Male, "enter your age")]
    public Int32? Age { get; set; }
}
public enum Sex
{
    Female = 1,
    Male = 2
}
Note we decorated the Age property with RequiredIf attribute, that we will create and it inherits ValidationAttribute class and override IsValid method.

The RequiredIf attribute accepts three pramaters in its constructor, first parameter is the name of the property will affect the validation (Sex property), second parameter is the value of that property that make the Age is required(Male), and third parameter is the error message that will be displayed if the validation failed.
public class RequiredIfAttribute : ValidationAttribute
{
    private String PropertyName { get; set; }
    private String ErrorMessage { get; set; }
    private Object DesiredValue { get; set; }

    public RequiredIfAttribute(String propertyName, Object desiredvalue, String errormessage)
    {
        this.PropertyName = propertyName;
        this.DesiredValue = desiredvalue;
        this.ErrorMessage = errormessage;
    }

    protected override ValidationResult IsValid(object value, ValidationContext context)
    {
        Object instance = context.ObjectInstance;
        Type type = instance.GetType();
        Object proprtyvalue = type.GetProperty(PropertyName).GetValue(instance, null);
        if (proprtyvalue.ToString() == DesiredValue.ToString() && value == null)
        {
            return new ValidationResult(ErrorMessage);
        }
        return ValidationResult.Success;
    }
}
In the IsValid method we get the current instance of RegisterationModel class using ValidationContext object and get the value of the Sex property then compare it with the desire value(Male) which make the Age is required. If the current value of Sex property equal the desired value then IsValid will return new ValidationResult object with the supplied error message.

Unfortunately this technique is working in server side only. You can download sample code here

Comments

  1. Thank you very much - this post saved me time.

    ReplyDelete
  2. Sorry, but it returns error message although the related field is filled in addition to controlled field's value is desired value. I mean that for example there is 2 field i.e. "isWorking" and "workingCity". When isWorking field is selected as "Yes" the workingCity field must be validated. There is no problem until this step. However, although workingCity field is filled, the validation error message remains after submitting the form. What might the problem? In addition to this, it would be better if there is an update enabling to work on both server and client side.Any idea?

    ReplyDelete
    Replies
    1. I cannot say what is the problem in your code exactly, but I used it in many projects and worked correctly.

      Delete
  3. Fixed my problem, thanks!

    ReplyDelete
    Replies
    1. return new ValidationResult(CustomErrorMessage, new[] { context.MemberName });

      This is to ensure that a validation result is correctly associated with a field when using a custom validation attribute, pass the validation context's MemberName when creating the ValidationResult:

      Delete

Post a Comment

Popular posts from this blog

ASP.Net MVC : ActionLink with bootstrap icon

Android : How to change progress bar color at runtime programmatically?