A brief comparision of Traditional vs Unobtrusive JavaScript Validation in MVC 3

A Brief Overview

With MVC 3, Client side validation has been enabled by default instead of having to explicitly declaring it in the view using the following code nugget.
ASPX View Engine
<%:Html.EnableClientValidation() %>
Razor View Engine
@{Html.EnabledClientValidation();}
This default behaviour is set inside the web config as show below.
<appSettings>
    <add key="webpages:Version" value="1.0.0.0"/>
    <add key="ClientValidationEnabled" value="true"/>
    <add key="UnobtrusiveJavaScriptEnabled" value="true"/>
</appSettings>
As you can see there is also another element inside the appSettings node named UnobtrusiveJavaScriptEnabled.
This single magical element (when true that is) makes all your validation alot easier to make dynamic, and also maintain in your client script.

The Nuts and Bolts

So lets take a quick look at traditional validation and how it is emitted to the client side for our validation libraries to pick up.
Here is our model we will be validating
public class UserViewModel
    {
        [Required]
        public string FirstName { get; set; }
        [Required]
        public string LastName { get; set; }
        [Required]
        public DateTime DateOfBirth { get; set; }
    }
 
Here is the emitted HTML with Unobtrusive JavaScript Disabled (traditional validation)
<form action="/" id="form0" method="post">
	<div id="validationSummary">
		<ul>
			<li style="display:none"></li>
		</ul>
	</div>    
	<fieldset>
        <legend>UserViewModel</legend>

        <div>
            <label for="FirstName">FirstName</label>
        </div>
        <div>
            <input id="FirstName" name="FirstName" type="text" value="" />
            <span id="FirstName_validationMessage"></span>
        </div>

        <div>
            <label for="LastName">LastName</label>
        </div>
        <div>
            <input id="LastName" name="LastName" type="text" value="" />
            <span id="LastName_validationMessage"></span>
        </div>

        <div>
            <label for="DateOfBirth">DateOfBirth</label>
        </div>
        <div>
            <input id="DateOfBirth" name="DateOfBirth" type="text" value="" />
            <span id="DateOfBirth_validationMessage"></span>
        </div>

        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
</form><script type="text/javascript">
//<![CDATA[
if (!window.mvcClientValidationMetadata) { window.mvcClientValidationMetadata = []; }
window.mvcClientValidationMetadata.push({"Fields":[{"FieldName":"FirstName","ReplaceValidationMessageContents":true,"ValidationMessageId":"FirstName_validationMessage","ValidationRules":[{"ErrorMessage":"The FirstName field is required.","ValidationParameters":{},"ValidationType":"required"}]},{"FieldName":"LastName","ReplaceValidationMessageContents":true,"ValidationMessageId":"LastName_validationMessage","ValidationRules":[{"ErrorMessage":"The LastName field is required.","ValidationParameters":{},"ValidationType":"required"}]},{"FieldName":"DateOfBirth","ReplaceValidationMessageContents":true,"ValidationMessageId":"DateOfBirth_validationMessage","ValidationRules":[{"ErrorMessage":"The DateOfBirth field is required.","ValidationParameters":{},"ValidationType":"required"}]}],"FormId":"form0","ReplaceValidationSummary":false,"ValidationSummaryId":"validationSummary"});
//]]>
</script>
 
Here is the emitted HTML with Unobtrusive JavaScript Enabled
<form action="/" method="post">    
    <fieldset>
        <legend>UserViewModel</legend>

        <div>
            <label for="FirstName">FirstName</label>
        </div>
        <div>
            <input data-val="true" data-val-required="The FirstName field is required." id="FirstName" name="FirstName" type="text" value="" />
            <span data-valmsg-for="FirstName" data-valmsg-replace="true"></span>
        </div>

        <div>
            <label for="LastName">LastName</label>
        </div>
        <div>
            <input data-val="true" data-val-required="The LastName field is required." id="LastName" name="LastName" type="text" value="" />
            <span data-valmsg-for="LastName" data-valmsg-replace="true"></span>
        </div>

        <div>
            <label for="DateOfBirth">DateOfBirth</label>
        </div>
        <div>
            <input data-val="true" data-val-required="The DateOfBirth field is required." id="DateOfBirth" name="DateOfBirth" type="text" value="" />
            <span data-valmsg-for="DateOfBirth" data-valmsg-replace="true"></span>
        </div>

        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
</form>

The Explaination

As you can see the main difference between the 2 is that when UnobtrusiveJavaScriptEnabled=”false”  it generates a CDATA snippet and serialized into standard MVC validation when the browser parses the page. A few problems that I have experienced with this is if you have multiple forms that require validation on the same page, lets say a form and a modal popup, if they have similar property names validation goes a little hay wire. (and trust me it can drive you nuts!)
But when UnobtrusiveJavaScriptEnabled=”true” all the “validation” is attached to the dom elements themselves and can be translated by a helper javascript library into appropriate jQuery validation rules and messages. Additionally, it’s also easier to validate sections or add addtionally validation rules dynamically as you are leveraging jQuery Validation.
Also another important thing to point out is the difference between these 2 forms is that when UnobtrusiveJavaScriptEnabled=”true” it uses jQuery validation and the other usesMicrosoftMVCValidation.
All in all im extremely excited to roll this validation logic into applications i’m developing and will make validation even easier, especially in very specific and obscure scenarios!.
In my next post i’ll be talking about how we can leverage this form of validation with custom data annotations to validate on both the client and server side! (with examples!)

Comments are closed.