Using the ‘Remote’ Attribute for Async Validation in ASP.NET MVC

Validation is an integral part of any input process in any computer software. As the saying goes ‘never trust anything the user gives you’. On the web, there are various ways of validating user input, some happen on the web-browser itself, some happen on the server after a user submits a form of data.

ASP.NET MVC 3.5 onwards supports various Data Annotation attributes that you can decorate your View Model with. The Data Annotations combined with Unobtrusive Client Side Validation using jQuery.Validation framework takes care of most common validation scenarios. However there are times when we want one special feature that is difficult to achieve using either pure client side or pure server side validation functionality built in. For such cases, ASP.NET MVC supports an attribute called ‘Remote’. The ‘Remote’ attribute takes in a Controller Action name and wires up the required JavaScript to do an Async Get operation on change of value in the UI.

Today we will see how we can use the ‘Remote’ attribute to enhance the default Registration page that comes with ASP.NET MVC4 Internet template. You can adapt it for validating any text on the server side.

Use Case for Async Server-Side Validation

Let’s start off by creating an ASP.NET MVC application (I am using MVC 4RC here, but you could use MVC3 with .NET 3.5 SP1 too).

Step 1: Select the ‘Internet Application’ Template. This adds the AccountController and related Account related Views.

internet-application-template

Step 2: Update the web.config’s connection string setting to point to the correct database and update the Database name. Also notice the two attribute ClientValidationEnabled and UnobstrusiveJavaScriptEnabled. These two attributes help wire up the DataAnnotations specified on the Model with the validations performed by the jQuery.Validation framework.

web-config-changes

Step 3: Run the Application and click on Register on the top right corner.

register-link

Step 4: Register using valid registration details


first-user-registration

Step 5: Once registered, log out and go to the Registration page again. Provide the same username as you provided earlier, put in all other details correctly and hit Submit. System comes back with an error saying User already exists.

second-user-registration-postback

The User in this case was warned of an issue after they hit Submit. It would be really nice if the User were warned of this issue as soon as they entered the User name. How can the User Name be validated? It is definitely not a client side validation as the list of existing users is only available on the server. For these kinds of scenarios we use the ‘Remote’ attribute for firing a server side Ajax call and doing the validation on the server side, keeping the existing form intact.

Setting up the Remote Attribute

To add the Async validation functionality we need to decorate our Model with an Attribute called ‘Remote’ and specify the Controller and Action method that will handle the Async request. This is done as follows

Step 1: Open the AccountModels.cs and navigate to the ‘RegisterModels’ class. On the UserName property, add the Remote attribute as follows. The ‘VerifyUserExists’ is the Action method on the ‘Account’ controller. We could specify a named parameter in the Remote attribute as ErrorMessage=’User Already Exists’, but we want to reuse the same message as the server side validation. So instead of duplicating text, we will retrieve it appropriately in the Action method.

register-models-class-updated

Step 2: Open the AccountController.cs and add a Method VerifyUserExists. This returns a JsonResult. Decorate the method with AllowAnonymous because we want to access this method at the time of Registration, which is done Anonymously.

Step 3: In the VerifyUserExists method, check for the UserName using the Membership provider. If user already exists, return the same error message that is returned on Server Side validation. If the user does not exist return true.

verify-user-exists-method

The Unobtrusive jQuery validator will treat any non-boolean value as false. So if no explicit ErrorMessage is provided, it will display the value that is returned. In our case we are returning the error message that we want to display.

Step 4: Open the Register.cshtml. The form uses a ValidationSummary helper to show a summary of all errors on server side submits. However we want to show the validation result immediately. So we add a @Html.ValidationMessageFor(m => m.UserName) to the UserName field. So if the Remote validator comes back with error it is shown immediately next to the field.

That’s it, we are all set with our Async validation for UserName. Run the application and try to create another user with the same name as the existing user. Notice how the error message comes up almost instantly. Warning the user before too many other elements have been populated.

username-validation-async

Conclusion

Remote attributes provide an easy way for doing server side validations where client-side validation is not possible and we want to provide an Ajaxified experience to the end-user that does not involve a lot of full page Postbacks.

ASP.NET MVCs validation framework is pretty extensive and has other extensibility points like custom Client Side validators. We will explore these in future, but for mandatory server side validations Remote attributes sit in a nice middle-ground of doing server side validations and maintaining near-client-side-validation interactive-ness.

Download the Zip file

Repository at - https://github.com/devcurry/RemoteValidationAttribute




3 comments:

Diego Correa said...

Excellent :D. Congratulations.

sharanbabu said...
This comment has been removed by the author.
sharanbabu said...

When you open the same page(in which the remote validation is used) in two tabs and logout in one tab and in the other tab if you type something in the username field, what happens to this remote call? How to handle this and redirect to login page?