Note: I’m relatively new to MVC3.
Input validation seems to be pretty nice with this framework, where you can just say [Required] and both client and server side validation just works from there. But what if I would like to implement conditional validation?
Scenario: I will have a dropbox box that requires you to choose one of 2 options. If option 1 is selected, 2 text input fields will appear and both are required. If option 2 is selected, 2 radio buttons will appear and you are required to select one of them. How can MVC3 validation achieve this?
Obviously, in the Model we can’t have just standard required validation, as some fields won’t be submitted depending on which drop-down option we choose.
Really? The scenario you describe is a perfect example of the limitations of using data annotations for validation.
I will try to explore 3 possible techniques. Go to the end of this answer and the third technique for the one I use and recommend.
Let me just before start exploring them show the controller and the view that will be used for the 3 scenarios as they will be the same.
Controller:
View:
script:
Nothing fancy here. A controller that instantiates a view model that is passed to the view. In the view we have a form and a dropdownlist. Using javascript we subscribe to the change event of this dropdownlisty and toggle different regions of this form based on the selected value.
Possibility 1
The first possibility is to have your view model implement the IValidatableObject. Bear in mind that if you decide to implement this interface on your view model you shouldn’t use any validation attributes on your view model properties or the
Validatemethod will never be invoked:What’s nice about this approach is that you could handle any complex validation scenario. What’s bad about this approach is that it’s not quite readable as we are mixing validation with messages and error input field name selection.
Possibility 2
Another possibility is to write a custom validation attribute like
[RequiredIf]:and then:
What’s nice about this approach is that our view model is clean. What’s bad about this is that using custom validation attributes you might quickly hit the limits. Think for example more complex scenarios where you would need to recurse down to sub-models and collections and stuff. This will quickly become a mess.
Possibility 3
A third possibility is to use FluentValidation.NET. It’s what I personally use and recommend.
So:
Install-Package FluentValidation.MVC3in your NuGet consoleIn
Application_Startin yourGlobal.asaxadd the following line:Write a validator for the view model:
And the view model itself is a POCO:
What’s good about this is that we have a perfect separation between the validation and the view model. It integrates nicely with ASP.NET MVC. We can unit test our validator in isolation in a very easy and fluent way.
What’s bad about this is that when Microsoft were designing ASP.NET MVC they opted for declarative validation logic (using data annotations) instead of imperative which is much better suited to validation scenarios and can handle just anything. It’s bad that FluentValidation.NET is not actually the standard way to perform validation in ASP.NET MVC.