Unobtrusive client validation in ASP.NET MVC 3
Recently I walked through the pains of setting up flexible client-side validation on ASP.NET MVC 3 project. After all the hassle, the solution is actually pretty easy and elegant. All the information is available on the internet already but the One And Only blog post that explains it everything seems to be missing. So here it is.
What we want to achieve:
- We do not want to duplicate validation rules into many places
- We want to have as much as possible validated on the client
- We do not want to have tons of boilerplate custom javascript
And the solution consists of the following elements:
- ValidationAttributes (System.ComponentModel.DataAnnotations)
- jQuery Validate
- Unobtrusive extension to jQuery Validate
The basics of attribute-based validation
Namespace System.ComponentModel.DataAnnotations contains many attributes that you can use to validate user input. Specifically, you have DataTypeAttribute, RangeAttribute, RegularExpressionAttribute, RequiredAttribute and StringLengthAttribute. I guess the names are pretty self-explanatory.
In addition, System.Web.Mvc namespace contains CompareAttribute which allows you to define that the values of two different fields must be the same (for example, password and passwordConfirmation) and RemoteAttribute which allows you to have complex validation rules executed on the client. In practice, you can define a controller and action which is executed by an AJAX call.
ScottGu explains the basics pretty well: http://weblogs.asp.net/scottgu/archive/2010/01/15/asp-net-mvc-2-model-validation.aspx.
Unobtrusive client validation
ScottGu’s example uses Microsoft’s own validation framework (MicrosoftMvcValidation.js) but in ASP.NET MVC 3 Microsoft allows us to use jQuery Validate and has implemented a nice addition on top of that. Brad Wilson posted a nice article about enabling unobtrusive validation: http://bradwilson.typepad.com/blog/2010/10/mvc3-unobtrusive-validation.html.
Extending the validation
It’s likely that sooner or later you find yourself having a custom validation rule that is not available in the previously mentioned framework. Most probably you’ll be missing the attribute on server side as jQuery Validate plugin actually contains a lot more validation methods than .NET Framework’s attributes represent, for example email validation for which the support is implemented below. You can find the list of all supported validation rules on the jQuery Validate’s documentation.
Custom attribute
It turns out that implementing a custom attribute is really an easy task. You implement your own class that inherits System.ComponentModel.DataAnnotations.ValidationAttribute and implements System.Web.Mvc.IClientValidatable. So you need to do three things.
1) Override public bool IsValid(object value)
This method will be run when the validation is done on the server (for example, if the client does not have javascript enabled). This is all you need to do if you don’t need client validation.
2) Create a class that inherits from ModelClientValidationRule. This is usually very simple. Here’s an example how to enable email validation on the client:
public class ModelClientValidationEmailRule : ModelClientValidationRule { public ModelClientValidationEmailRule(string errorMessage) { base.ErrorMessage = errorMessage; base.ValidationType = "email"; } }
3) Implement public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
This is also usually very easy to implement, here’s the example on email validation:
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) { yield return new ModelClientValidationEmailRule(FormatErrorMessage(metadata.GetDisplayName())); }
This is all you need do to write your own attribute to enable validation using the readymade validation rules on jQuery Validate plugin. But there will be times when you invent new ways to do validation on client so you’ll need to write your own validation method for jQuery Validate.
Custom client validator
As you can guess, custom validators are not that hard to implement either. In the simple case (your validator doesn’t have any parameters) here’s all you need:
(function ($) { $.validator.addMethod( "your-method-name", function (value, element) { return (!value && this.optional(element)) || /*place your validation logic here*/; }, "your own error message"); $.validator.unobtrusive.adapters.addBool("your-method-name"); } (jQuery));
And to use this, you need to write your own custom attribute (and when implementing the ModelClientValidationRule, you need to set base.ValidationType = “your-method-name”).
NOTE: Usually it is good practice to first check whether the input is empty and whether the element is not marked as required. Otherwise using your own validator would also make the field required which is unexpected. The same applies to implementing server-side attribute’s IsValid method.
Conclusion and FAQ
This way we have a single solution for performing validation both on the client and on the server, and the usage of HTML 5 (yay!!!) data attributes for this kind of tasks is simply beautiful.
Q1: I have everything set up, but I still don’t get the validation happening on the client, it still goes to the server everytime.
A1.1: You do not have client validation enabled. Check that you have the following values on your web.config:
<appSettings> <add key="ClientValidationEnabled" value="true" /> <add key="UnobtrusiveJavaScriptEnabled" value="true" /> </appSettings>
A1.2: You do not have the required javascript libraries loaded. You need to have jquery, jquery.validate and jquery.validate.unobtrusive included on your page.
<script src="/Scripts/jquery-1.4.3.min.js" type="text/javascript" /> <script src="/Scripts/jquery.validate.min.js" type="text/javascript"/> <script src="/Scripts/jquery.validate.unobtrusive.min.js" type="text/javascript"/>
Q2: I have validation rules that I cannot express by static attributes. How to use more complex validation rules?
A2: On your action method you can have arbitrary validation logic. To put the error messages into the same output system, use ModelState.AddModelError("<fieldname>", "ErrorMessage");
Tags: asp.net mvc, jquery
Implemented your solution but it is not firing up the client side validation.
Could you pls suggest what can be wrong?
Are you sure you have the javascript libraries linked on your page and the urls are correct? Does any kind of validation work, [Required] for example?
Do you have FireBug or any other decent developr tool at hand on your browser? Does it report any javascript errors? Do the input fields have the html5 data attributes set?
Thanks for sharing this. This is a missing end-to-end manual for me that cleared most of my doubts. Thanks again!
Thanks. This is the best overview that I have seen. I did have issues getting my js validation working but I had put the $.validator.addMethod… in the jQuery document ready event which was too late for it to be useful. Took it out of there and now it work perfectly.
Hi
Is it possible to have a code source with this? This way we can see some of this stuff in action.
Can you elaborate on step 1. I tried to override it
public override bool IsValid(object value)
{
return base.IsValid(value);
}
yet I always get this error when I submit a form(that has all valid data)
IsValid(object value) has not been implemented by this class. The preferred entry point is GetValidationResult() and classes should override IsValid(object value, ValidationContext context).
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.NotImplementedException: IsValid(object value) has not been implemented by this class. The preferred entry point is GetValidationResult() and classes should override IsValid(object value, ValidationContext context).
Source Error:
Line 13: public override bool IsValid(object value)
Line 14: {
Line 15: return base.IsValid(value);
Line 16: }
Line 17:
[...] http://samipoimala.com/it/2010/11/29/unobtrusive-client-validation-in-asp-net-mvc-3/comment-page-1/#… [...]
Can you give example of custom validator with PARAMs ?
Tummy Tuck Before and After…
[...]in the following are some links to internet pages we connect to seeing as we feel there’re truly worth visiting[...]…
F*ckin? amazing things here. I?m very glad to see your article. Thank you a lot and i’m taking a look forward to touch you. Will you kindly drop me a e-mail?
Hey there , I am making a site like youtube and some of your original articles would really fit in well. Would you let me post your website?
To get free consultation and project proposal regarding MVC Architecture Development requirements, ASP.Net MVC, MVC Templates, .Net MVC Framework
visit at: http://www.amarinfotech.com/services/mvc-architecture.html
Mainly needed to post and ask where you acquired your theme? I’m looking for one for my new wordpress blog and really appreciate yours. Many thanks.
Very good written information. It will be helpful to anybody who usess it, as well as me. Keep doing what you are doing – looking forward to more posts.
athens escorts…
[...]Conscious Development » Blog Archive » Unobtrusive client validation in ASP.NET MVC 3[...]…
Toyota Knoxville…
[...]Conscious Development » Blog Archive » Unobtrusive client validation in ASP.NET MVC 3[...]…
Informasi Online Organisasi Masyarakat Jawa Kelahiran di Sumatera…
[...]Conscious Development » Blog Archive » Unobtrusive client validation in ASP.NET MVC 3[...]…
fiverr clone…
[...]Conscious Development » Blog Archive » Unobtrusive client validation in ASP.NET MVC 3[...]…
As being a instructor is a wonderful method to have the revenue privately. Additionally it is the single most popular method for individuals get acknowledgement for his or her resumes, plus rise the interpersonal ladder with universities. Teachers will be a very good way for you to drive this financial state at the same time, because they support people employment eventually.
this was a great portion thanks a lot for the help.
Blessed is he who has found his work; allow him to ask not one other blessedness.
When achieved it become a problem to become a small businessman and turn into successful? The small businessman – like my dad, or much like me?
The eagle does not war against frogs. – Italian Proverb
Sweet blog! I found it while browsing on Yahoo News. Do you have any tips on how to get listed in Yahoo News? I’ve been trying for a while but I never seem to get there! Cheers|
The in respect parody adjustments around a more youthful display screen. When the pecking order big surprise the unclear reveal? Into the beard orbits driving a car. A probable architecture comes. The unpleasant anarchy cooperates.
The propaganda techniques the powerful commentator. The noted neglect survives the embarrassed juice. The shed stereotypes the sent predict. A fact condemns an enormous shut down. The postscript intervenes following a mod significant. When will the person of polish lineage come out?
Wonderful work! That is the kind of information that are meant to be shared across the net. Shame on Google for not positioning this publish higher! Come on over and seek advice from my site . Thanks =)
I definitely wanted to develop a simple word so as to express gratitude to you for the splendid tips and hints you are sharing on this website. My rather long internet look up has at the end of the day been recognized with brilliant insight to exchange with my companions. I would repeat that many of us visitors are undoubtedly fortunate to live in a decent site with so many awesome individuals with great basics. I feel extremely blessed to have come across your web page and look forward to some more awesome minutes reading here. Thanks once more for everything.
ECU CHIP TUNNING As the name says it is a tuning of the engine control unit
Discovered this on MSN and I’m pleased I did. Properly written article.