Client-Side Validation in Downlevel Browsers
By Scott Mitchell
Introduction
Last week I wrote an article called A Look at ASP.NET's Adaptive Rendering that examined how the ASP.NET Web controls emit different HTML based on the browser that was visiting the page. This technique is referred to as adaptive rendering. Adaptive rendering has its advantages in that, ideally, appropriate markup is generated based on the requesting browser. However, by default ASP.NET is configured to send HTML 4.0-compliant HTML to only Internet Explorer, and sends HTML 3.2-compliant HTML to all non-Microsoft browsers, even though modern, non-Microsoft browsers such as Mozilla, Netscape 6.0+, Opera, and others can handle HTML 4.0. In A Look at ASP.NET's Adaptive Rendering we saw how to configure a Web application or Web server to have the Web controls render HTML 4.0-compliant markup for modern, non-Microsoft browsers.
While ASP.NET can be easily configured to render HTML 4.0-compliant markup for additional browsers, one thing that this technique does not solve for is that of client-side validation with the validation controls. ASP.NET provides a number of validation controls - RequiredFieldValidator, CompareValidator, and so on - that are useful for ensuring that a user enters valid values into form fields. With Internet Explorer, these controls emit client-side JavaScript that perform the validation on the client-side in addition to the server-side. For non-Microsoft browsers, only server-side validation is possible. Unfortunately, tweaking ASP.NET to get the validators to use client-side validation for non-Microsoft browsers is not as easy as one would hope. This article examines why and presents a workaround.
How the Validation Controls Render Client-Side Script
All of the ASP.NET validation controls are derived from the
System.Web.UI.WebControls.BaseValidator class.
The BaseValidator class defines the methods and properties common to all validation controls. One
of the things the BaseValidator class does is determine whether or not client-side script should be
rendered. This is accomplished in the PreRender stage by the class's DetermineRenderUplevel() method.
This method indicates that client-side scripting should be emitted if the following three conditions hold true:
- The validator's
EnableClientScriptproperty is True (the default) - The requesting browser's
MSDomVersionproperty is version 4.0 or higher. - The requesting browser's
EcmaScriptVersionproperty is version 1.2 or higher.
MSDomVersion and EcmaScriptVersion are properties of the Browser object.
As discussed in A Look at ASP.NET's Adaptive Rendering, the Browser
object contains read-only properties that describe the capabilities of the requesting browser. These capabilities
are determined by the <browserCaps> settings in the maching.config file or Web.config file.
Given this, you might think that enabling client-side validation in modern, non-Microsoft browsers would be as simple
as tweaking the maching.config file, setting the MSDomVersion to 4.0 or greater for
the appropriate User-Agent string for these browsers. This will, indeed, cause the client-side script for the validation
controls to be emitted, but, sadly, things will still not work.
The reason modern, non-Microsoft browsers do not support client-side validation in the validation controls is because
of the client-side script emitted by BaseValidator. The client-side validation script emitted by BaseValidator
includes, among other things, a JavaScript block that creates an array of the validators. This array, then, can be
enumerated on the client-side script to check the validity of all of the validation controls. This array is registered
in the BaseValidator's RegisterValidatorDeclaration() method, but unfortunately uses
the client-side script document.all[validatorID]. An example of the array declaration when rendered
on an ASP.NET Web page can be seen below:
<script language="javascript">
|
The problem with document.all[ID] is that Microsoft's Internet Explorer is the only browser that
supports this non-standard technique for referencing an element in the HTML document. The standard way (which Internet
Explorer does support, along with Mozilla, Netscape, Opera, and others), is: document.getElementById(ID).
So, the script emitted by the BaseValidator class will do nothing but generate JavaScript errors in non-Microsoft
browsers. Bummer.
On top of the document.all snafu, there are some minor issues in the WebUIValidation.js JavaScript
file ASP.NET uses to perform validation. For example, Mozilla doesn't like the use of the variable name final (on lines
341, 349, 356, and 369). These issues, though, can be easily fixed since WebUIValidation.js
can be modified with any ol' text editor. Fixing the Internet Explorer-only document.all emitted by
BaseValidator requires much more work, as we'll soon see.
Fixing ASP.NET's Validation Controls to Support Client-Side Validation for Modern, Non-Microsoft Browsers
In order to fix the client-side validation for non-Microsoft browsers, we need to replace the
document.all[ID]
portion in the BaseValidator class with a standards-compliant document.getElementById(ID).
There are a few ways to do this.
- Create a new class that derives from
BaseValidator. This class could then override theRegisterValidatorDeclaration()method and emit the proper script. Next, you would have to create a new class for each of the validation controls (RequiredFieldValidator, CompareValidator, and so on), having these derive from the extendedBaseValidatorclass. - Build everything from scratch. This entails building a
BaseValidator-like class from the ground up, followed by creating the validation controls derived from the newBaseValidator-like class. - Delegate this to someone else. This is my favorite choice for most things! :-) For instance, you can use Paul Glavich's free DomValidators controls. These controls are build from the ground up, and emit only standards-compliant script. The DomValidators include the complete source code and instructions on how to start using the DomValidators in an ASP.NET application.
There are also third-party commercial components available. For example, Peter Blum offers a set of validation controls he calls Professional Validation and More. Like Paul Glavich's DomValidators, Peter's control library was written from the ground up. In addition to providing the five base validation controls, Peter's product includes an additional 17 more validation controls, such as WordCountValidator, CreditCardNumberValidator, and others. There are a bevy of other features worth checking out as well.
As Peter and Paul and shown, having suitable client-side script emitted for modern, non-Microsoft browsers is indeed possible, but not as simple as it should be. Of course, all of this will be taken care of with ASP.NET 2.0, but we still live in a 1.x world.
Conclusion
The default ASP.NET validation controls do not provide a working client-side script model for modern, non-Microsoft browsers due to the fact that proprietary script -
document.all[ID] - is used in place of standards-compliant
script - document.getElementById(ID). Client-side support can be added, but at the cost of
recreating the validation controls. Fortunately, the work has already been provided by Paul Glavich,
so you can use his DomValidators
validation controls if you are needing to support client-side validation with non-Microsoft browsers.
By applying the techniques discussed in this article along with the techniques mentioned in A Look at ASP.NET's Adaptive Rendering, you can make ASP.NET render identically for both Internet Explorer and equally capable non-Microsoft Web browsers.
Happy Programming!




