Warning: Please consider that this post is over 6 years old and the content may no longer be relevant.
Need to perform validation on a model’s property based on some other state of the model? Here’s a way to achieve it using the IValidatableObject interface and data annotations.
In our example project we want to validate the state field is a valid Australian state if the country field is “Australia”.
Any model that implements IValidatableObject in MVC3 (note this doesn’t work in MVC2) will get it’s Validate method called when validating the object.
To define the conditional validation we’ll use a ConditionalValidationAttribute which identifies a method to call to perform the validation. The method must be static, accept at least one parameter (the value of the property to be validated), optionally accept a second context parameter (this will be the object whose property is being validated) and return a ValidationResult.
The ModelBase class brings this all together. The constructor builds a dictionary of ConditionalValidationAttributes for each property and it implements the IValidatableObject.Validate method to loop through all the ConditionalValidationAttributes and validate them.
Note that the IValidatableObject.Validate method is called after all data annotations have been successfully validated. So if you have some properties with a RequiredAttribute, the required field error message will show and the user will need to fix this before our model’s Validate messages are displayed.
Here’s the full code for ModelBase.cs:
Note that when we call the ConditionalValidationAttribute.IsValid method we pass in ‘this’ as the context so we have a reference to the object being validated.
A few notes here:
The constructor tries to find an appropriate method using reflection. If there are multiple overloads of the method then the one with 2 parameters will be chosen.
The first parameter of the validation method can be of any type. Type conversion is attempted on the value to validate to match the method signature. I.e. the first (value) parameter can be object, string, int, etc.
A generic error message can be supplied to the ConditionalValidationAttribute. If the validation method doesn’t set an error message when it returns a validation error, the ConditionalValidationAttribute.ErrorMessage property will be used.
And a sample model User.cs:
Download the example by clicking the button below.