MVC 3 Unobtrusive Client Validation and Unobtrusive Ajax Overview
As you may be aware, ASP.NET MVC 3 allows the possibility of using unobtursive client validation and unobtrusive Ajax. If enabled, in a nutshell this means that the stock Microsoft JavaScript libraries for both Ajax and validation (MicrosoftAjax.js and MicrosoftMvcValidation.js respectively) have been effectively swapped out to use unobtrusive equivalents. Unobtrusive means that HTML5 style “data-*” attributes are used to denote validation and Ajax rules on their respective HTML elements (very nice in my opinion!) There is also something else you should be aware of that didn’t immediately strike me: Unobtrusive also means all validation and Ajax requests go through jQuery libraries (jquery-1.5.1.js and the excellent third party jquery.validate.js respectively). jquery.validate.unobtrusive.js and jquery.unobtrusive-ajax.js are Microsoft libraries that sit on top of the “core” jQuery execution of these tasks but at it’s core it’s using jQuery!
The fact that all Ajax and validation goes through jQuery is a pretty exciting prospect indeed. In my experience I have found jQuery libraries to be better documented and more extensible than their Microsoft equivalents (though MS did an excellent job with their libraries as well.) As cool as this change is there might be one issue with all this though that I personally experienced: I want to upgrade to MVC 3 but what about my existing MVC 2 application?
In my case I had made some hooks into MicrosoftAjax.js and MicrosoftMvcValidation.js directly to get some extra functionality that was not provided by stock. This of course broke any of these hooks which needed to be transfromed into jQuery + unobtrusive library hooks. Not bad that I only have to worry about all Ajax going through one library though (jQuery)!
Client Validation in MVC 3
This fact brings me to the main point of this post. ASP.NET MVC is great, it gives you client-side validation essentially for free provided you define some DataAnnotations on your ViewModel. My team has even gone as far as T4 generating these annotations straight from the underlying EDMX model but that is another story altogether… One of the major short-falls I experienced with MVC 2 and 3 was the lack of client validation on a <form> that was loaded via AJAX. Furthermore in MVC 2 the Microsoft AJAX libraries didn’t even consistently execute the jQuery “document ready” event $(function(){…});
Having client validation as much as possible was a requirement for me so did some googling and quickly found Adam Craven’s post about a solution to this: a library to extend Microsoft validation and Ajax to work as needed, AjaxLoadedContentScriptFix.js. This library works great until you start using MVC 3 when you aren’t using the expected MS libraries anymore..
The Fix
jQuery executes “document ready” events retrieved on Ajax but there is still one more problem… the validation!
Fortunately the “fix” to enable client validation on any new <form>s loaded into the DOM via Ajax is very simple in MVC 3… just hook into jQuery’s ajaxComplete handler and re-parse the DOM for any new <form> fields that may require client side validation.
$(function () { $(document).ajaxComplete(function(event, request, settings){ //re-parse the DOM after Ajax to enable client validation for any new form fields that have it enabled $.validator.unobtrusive.parse(document); }); });
The above solution works wonderfully on it’s own. Any new form loaded through Ajax has client validation parsed and hooked-up automatically, no extra “per-instance” code is required as long as the above code is placed in a “global” library.
You may also be wondering about the performance implications of re-parsing the whole DOM for validation after all Ajax events (after all you may have noticed that event even fires for each image in the new page loaded via Ajax for example). So far I haven’t noticed any performance problems. It may be possible to only re-parse validation for just the new content in the DOM (assuming the ajaxComplete firing was a result of HTML content being retrieved in the first place) but I hope this gets you on your feet.
Feel free to let everyone know if you have found a better solution in the comments, thanks for reading!
I wrote a 'Better Unobtrusive Ajax for ASP.NET MVC'. It can be found on https://github.com/dhlavaty/winf.unobtrusiveAjax.js It supports latest jQuery, has clean code and documentation. If someone is interested or want to contribute, I will appreciate it.
thx alot fantastic solution
Worked perfectly. Thanks!
Worked great!! Was searching for a solution to .valid() always returning true. My search ends here. Thanks a lot!