We recently refactored the validation on our HTML forms in a ASP.NET web application to simplify and reduce duplicate validation logic. Previously we had implemented duplicate validation logic in both JavaScript for client side validation and ASP.NET model validation on the server side. Both are needed but the duplicate code was starting to smell more than I liked.
ASP.NET Validation
By default ASP.NET model validation for properties with DataAnnotation attributes will run on every controller action execution. You can check the IsValid property on ModelState property of the base Controller class to control when the form data should be process or rejected. If you return the model back to the view and there are validation errors they will be displayed in the form with their corresponding fields.
Optionally you can also enable Unobtrusive jQuery Validation which will perform validation logic in the browser using jQuery for a small set of C# DataAnnotations including the following attributes: Required, Range, RegularExpression and StringLength. Validation failures in the browser will prevent the form from posting, which makes the web application less chatty and more efficient.
Here is a tutorial to setup model validation both server and client side.
Advanced Validation
Although this is helpful there is often more complicated/advanced model validation logic that must be performed. Some properties must be validated using the values of other properties. For example, the state field is required only when the country is USA (or a country that has states). The Required attribute won’t work for the state field in this case because it depends on the value of country.
The .NET folks were smart enough to think of this and provided a RemoteModelValidatorAttribute to help cover this case. This attribute instructs the browser to make an AJAX call back to the server to validate the property value. The server can return a true if the value is valid or an error message if invalid. This is validator is also helpful for values that must be validated against metadata in a database for example.
In most examples, a new controller action is created for each property that needs remote validation. This didn’t smell right either. Too much duplication.
RemoteModelValidatorAttribute
Instead what we really want is to run the full model validation logic and return any errors specific to the property being validated. It wouldn’t make sense to show validations for all properties under the single property.
The RemoteAttribute provides a AdditionalFields property where you can pass other field values that are needed for validation. In our case we want all the values passed back to the server. This could be done manually but that is too much work to implement and keep in sync as we add properties over time.
Instead we can create a new attribute which inherits from RemoteAttribute and automatically sets the AdditionalFields property with all the property names.
Next we can add the new attribute to any property that requires advanced validation.
Finally we must filter down the validation errors to only those that are related to the property being validated.
Please leave a comment below if this post was helpful to you, you have further questions or you have other feedback.
Happy Validating!
This appears to use an HTTP GET to contact the remote validator. How can this be modified to use POST rather than GET?
Add the parameter HttpMethod=”POST” when you use the attribute in your model class
Thank you. This is exactly what I needed. I have one question. When the form is submitted, do you run the validation logic again server side before completing the controller action? I’m wondering if there’s a way for a clever user to work around this kind of client side validation?
Yes, you should definitely run it again server side. Almost any client code can be altered so you can’t rely on it because of potential bad actors.
That’s what I thought, thanks. At least I can run the same methods client & server side. That definitely keeps it more DRY.