Unobtrusive Client-Side Validation


Introduction

JQuery Validation is an efficient, resilient and widely adopted solution for client-side validation. Since JQuery’s official support by Microsoft and the introduction of Unobtrusive Client Validation for .NET, it has become easier than ever to integrate with applications that use .NET forms.

There is a catch, however, and it arises if customised rules are implemented client-side.

When Unobtrusive Client Validation is enabled, the .NET framework will automatically configure JQuery Validation for each page. By default, it will parse type (and other) details of every field from attributes in their DOM elements and instantiate rules for them that mirror the requirements defined for their server-side counterparts. So far, so good.

The Problem

The trouble starts when a more customised rules configuration is required, other than the default one that Unobtrusive Validation employs. Say that you wanted to alter how the standard “required” rule works, making fields mandatory only if they are not read-only; one could use the depends keyword inside a rule declaration when configuring JQuery Validation, as shown in the example below:

$("form ").validate(
	{
		rules: {
			myField: {
				required: {
					depends: <b>myCustomFunction</b>
				}
			}
		}
	}
});

However, since Unobtrusive Validation already does that for you, the necessary configuration object is already instantiated by the system; and because of a surprisingly undocumented feature of JQuery Validation, further calls to the validate() method do not merge any of the new rules with the existing ones – they are simply ignored.

It is worth nothing that the validate() method doesn’t actually perform validation – it is simply used to instantiate the Validator object when called for the first time, and returns it each following time. The actual validation is performed by calling the valid() method on the target object.

So, by declaring our custom validation config in advance of the automatic one (outside of the $(document).ready() block) we will have precedence over it, but in turn it will make it useless, negating any advantage that Unobtrusive Validation brings to the table. Declaring our custom validation config after the automatic one (inside the $(document).ready() block) will simply cause it to be ignored.

The Solution

There is another way to resolve this, which involves directly manipulating the rules inside the validator object after they have already been declared, as shown in the example below:

$(document).ready(function() {
	if ($('form').validate() &amp;&amp; $('form').validate().settings) {
		var rule, ruleName;

		for (ruleName in $('form').validate().settings.rules) {
			rule = $('form').validate().settings.rules[ruleName];
			if (rule["required"]) {
				rule["required"] = <b>myCustomFunction</b>
			}
		}
	}
});

This resolution is slightly more intricate, but eventually it gets the job done nicely.

Additional Note

As a side note, all of this also means that custom validator adapters and methods on the client side must be declared outside of the $(document).ready() block, or likewise will be ignored – their existence or lack thereof is controlled by the plugin during its initialisation phase.

Leave a Comment

(required)