Full Remote Model Validation in ASP.NET

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.

https://docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions/hands-on-labs/aspnet-mvc-4-helpers-forms-and-validation#Exercise7

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.

https://docs.microsoft.com/en-us/aspnet/core/mvc/models/validation?view=aspnetcore-2.1#remote-validation

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!

5 thoughts on “Full Remote Model Validation in ASP.NET”

  1. This appears to use an HTTP GET to contact the remote validator. How can this be modified to use POST rather than GET?

  2. 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?

Leave a Reply