Field Input Validation

Summary

Introduction

Input fields in an HTML form unfortunately provide no support for data validation. For example, a text box field designed to collect the user's email address may end containing meaningless numbers or an invalid email format. With classic ASP, it was the developer's responsibility to create validation routines to ensure that field input was valid.

Luckily with ASP.NET, form field validation is very easy thanks to validation controls. Validation controls are Web controls used to ensure that the entered values in form fields meet developer-defined criteria. Specifically, validation controls point to other Web controls and it is these Web controls that validation controls validate. Since validation controls are Web controls, they can be added to an ASP.NET form just like any other Web controls using the <asp:WebControlName ...> format.

In general, form validation can take one of two forms: 

In client-side validation, the ASP page contains client-side JavaScript that is executed on the user's machine before the form is submitted back to the Web server. If the form fields are valid, the page is submitted, else some sort of a message box is presented to the user prompting him/her to add/correct field input. Client-side validation has the advantage that it runs on the client's machine without the need for a round-trip back to the Web server. Obviously, this improves performance and removes unnecessary load on the Web server. Its down side is that it requires the client to be able to execute JavaScript on his browser (some Web surfers explicitly turn off this feature). More importantly, client-side validation may pause a security risk as some clever users may attempt to bypass the validation process altogether.

Server-side validation on the other hand takes place after the form has been submitted but before form field data is processed. The main advantage is that server-side scripting will work regardless of the user's browser. It will also be impossible for user to bypass the validation process.

In ASP.NET, validation controls always use server-side form validation. However, if the user's browser also supports DHTML, client-side validation will be included as well. In fact, validation controls will automatically decide whether or not the requesting Web browser supports the required technologies to handle client-side form validation. To further refine this process, you can explicitly request that validation controls should never user client-side validation on a page-by-page basis. This can be down using the ClientTarget property on the Page directive:

<%@Page ClientTarget="DownLevel" %>
...

Required Field Validation

The RequiredFieldValidator  validation control is used to verify that a required field has been populated before the form has been submitted. For example, when a user logs on to a Web subscription, it might be required that the user name field and the password field be populated before submitting the form. Note: If ASP.NET identifies your browser as an 'uplevel' browser (IE 4 and above at the time of this writing - late 2003), client-side JavaScript and DHTML will be used to perform client-side validation as well. In such a case, as described above, you will not be able to submit the form until all fields have been validated. 

The following code shows how to attach field valuators. Note that Visual Studio.NET was used to place the validators on the HTML design screen. The Properties window was then used to set the key properties such as ControlToValidate, ID, Display, and ErrorMessage.:

<body MS_POSITIONING="GridLayout">
    <form id="Form1" method="post" runat="server">
        <asp:Label id="Label1" runat="server" >Username</asp:Label>
        <asp:TextBox id="txtPassword" runat="server"></asp:TextBox>
        <asp:Label id="Label2" runat="server">Password</asp:Label>
        <asp:TextBox id="txtUsername" runat="server"></asp:TextBox>
        <asp:Button id="btnLogin" runat="server" Text="Log Me In Scottie"></asp:Button>
        <asp:RequiredFieldValidator id="reqUserName" runat="server" ErrorMessage="Please enter user name"
             ControlToValidate="txtUsername" Display="Dynamic" ></asp:RequiredFieldValidator>
        <asp:RequiredFieldValidator id="ReqPassword" runat="server" ErrorMessage="Please enter password"
             ControlToValidate="txtPassword" ></asp:RequiredFieldValidator>
        <asp:Label id="lblLoginStatus" runat="server" ></asp:Label></form>
</body>

public class WebForm1 : System.Web.UI.Page
{
    protected System.Web.UI.WebControls.Label Label1;
    protected System.Web.UI.WebControls.TextBox txtUsername;
    protected System.Web.UI.WebControls.TextBox txtPassword;
    protected System.Web.UI.WebControls.Button btnLogin;
    protected System.Web.UI.WebControls.RequiredFieldValidator reqUserName;
    protected System.Web.UI.WebControls.RequiredFieldValidator ReqPassword;
    protected System.Web.UI.WebControls.Label lblLoginStatus;
    protected System.Web.UI.WebControls.Label Label2;

    private void Page_Load(object sender, System.EventArgs e)
    {
        lblLoginStatus.Text = "";
    }

    #region Web Form Designer generated code
    ...
    #endregion

    /* Whether this handler function gets called or not when the user clicks the log in button depends on
    the presence of ClientTarget="DownLevel" in the @Page directive. If this attribute is present then there
    will be no client-side validation and the Click handler will always be called. The Page.IsValid property
    then is used to determine whether user input was valid or not. If the ClientTarget="DownLevel" was not
    present in the Page directive, then this click handler will only be called if controls passed validation,
   
and in this case, it makes no sense to call Page.IsValid*/
    private void btnLogin_Click(object sender, System.EventArgs e)
    { 
        if (this.IsValid)
        {
            lblLoginStatus.Text = "Please wait while system logs you in...";
        }
        else
        {
            lblLoginStatus.Text = "Validation failed. Please resubmit required information.";
        }
    }
}

The following figures illustrate what happens when you attempt to log in. ClientTarget="DownLevel" was not present in the @Page directive for this page. Hence, clicking the log in button did not submit the request to the server (Click handler was not called) but instead, caused validation to take place on the client-machine. The second figure shows when validation went through. Clicking the log in button will now send a request to the server.

The RequiredFieldValidator can be used not only with TextBox controls but also with Radio Button, ListBox, and CheckBox controls. In the following example, a RequiredFieldValidator is used to ensure that the user actually selects a meaningful value. If the user attempts to submit the form without selecting another value, then the RequiredFieldValidator is activated. In this example, when the list box was created, the Properties window was used to populate the list box and select the first item as 'Selected'. For the RequiredFieldValidator an extra property was set - InitialValue. This value was set to "-- Select Location--" to tell the validator that this is the initial value and that it must be changed before the form can be validated:

Field Compare Validation

The CompareValidator validation control is useful to compare the value of a form input field to another hard-coded value, or event the value of another form field. For example, you could have a form input field asking the user for his age. Obviously, it makes no sense to enter an age less than zero. The CompareValidator validation control can also be used to ensure that an input value has a certain data type. For example, you could have a form input field asking the user for his name. Obviously, entering a number is not meaningful in this case.

The following two figures show the necessary settings for two CompareValidator controls each associated with a textbox control - one validator validates that entered age value is an integer and the other validates that entered salary value is greater than or equal to 100,000. Of special importance in each of these two Properties pages are the Operator and Type CompareValidator properties. The Operator property tell the validator what kind of compare operation to do (check for value or for type), and the Type operator tells the validator what should the type of data be in the control to be validated:

   

The following two IE screens illustrate the usage of the CompareValidator to check that Age value is an integer and Salary value is > 100,000.

Range Validation

The RangeValidator control, as the name implies, ensures that a form field entry falls within the specified range. These two values must be static, hard-coded values. To check if a value falls between a dynamic range, i.e., values entered by a user into other form fields, a CompareValidator control must be used.

 

Regular Expression Validation

All the examined validators so far had a specific purpose; RequiredFieldValidator ensures that certain form input fields are populated before a form can be submitted. CompareValidator ensures that certain form input fields successfully compare to a predetermined value (which can be static or dynamic), and RangeValidator ensures that certain form input fields have values that fall within a specified range.

The RegularExpressionValidator, however, is the most flexible and general validation control. As the name implies, RegularExpressionValidator checks a form input field against a developer-defined regular expression (a regular expression is a string with special characters that can be used to lookup specific patterns in another string. Check MSDN for more info). For example, the RegularExpressionValidator is ideal to checking that social security numbers, telephone numbers, email addresses, URLs and many others all meet their particular string format. Therefore, when collecting such information, the RegularExpressionValidator can be very helpful in ensuring that users enter data in the correct format.

Note: A RegularExpressionValidator control will report as valid a form input field if the user does not enter any data. Therefore, a RegularExpressionValidator is often used in conjunction with RequiredFieldValidator to ensure that requested data is entered in the correct format.

The following example shows all the required properties for a RangeExpressionValidator. Output follows:

Using a Custom Validator

The CustomValidator control  is often used when you want to perform some user-defined validation on an input control when all other validation controls are inappropriate. With the CustomValidator control, when the form is submitted, validation happens via a user-supplied event handler for the ServerValidate event. Note that the CustomValidator can also contain references to client-side functions that can perform the required validation (instead of going to the server) if the user's browser can handle client-side form validation. However, because ASP.NET validation controls always perform server-side validation, it is required that you provide a server-side validation function for the CustomValidator control. The client-side validation function is optional.

Creating Server-Side Validation Functions

The server-side event handler for the ServerValidate event must use the following signature:

public void ServerValidateHandler( object oSender, ServerValidateEventArgs e );

But keep in mind that the purpose of the CustomValidator Web control is to validate another Web control. This implies that the ServerValidate event handler needs to:

  1. Retrieve the value entered in to the Web control we wish to validate, and,
  2. Let the CustomValidator Web control know if the entry was valid. It is up to the developer to determine when an entry is valid or not.

These two tasks can be accomplished using the ServerValidateEventArgs parameters Value and IsValid.,The first property retrieves the value entered into the Web control we wish to validate, and this second property tells the CustomValidator Web control whether validation passes or fails.

public class CustomValidator : System.Web.UI.Page
{
    protected System.Web.UI.WebControls.Label lblSSN;
    protected System.Web.UI.WebControls.TextBox txtPassword;
    protected System.Web.UI.WebControls.Button Button1;
    protected System.Web.UI.WebControls.Label lblStatus;
    protected System.Web.UI.WebControls.CustomValidator CustomValidator1;

    private void Page_Load(object sender, System.EventArgs e)
    {
        lblStatus.Visible = false;
    }

    private void CustomValidator1_ServerValidate(object source, System.Web.UI.WebControls.ServerValidateEventArgs args)
    {
        // Get password
        string strPWD = args.Value;

        // Now perform the custom validation (check that password length is at least 8 digits)
        if (strPWD.Length < 8)
            args.IsValid = false;
        else
            args.IsValid = true;
    }

    private void Button1_Click(object sender, System.EventArgs e)
    {
        // Has this form been validated by the custom validator in ServerValidate evnet handler?
        if (this.IsValid)
        {
            lblStatus.Visible = true;
            lblStatus.Text = "Please wait while system logs you in ...";
        }
    }
}

<body MS_POSITIONING="GridLayout">
    <form id="CustomValidator" method="post" runat="server">
        <asp:Label id="lblSSN" runat="server" >Enter Password</asp:Label>
        <asp:TextBox id="txtPassword" runat="server" ></asp:TextBox>
        <asp:Button id="Button1" runat="server" Text="Log in"></asp:Button>
        <asp:CustomValidator id="CustomValidator1" runat="server" 
            ErrorMessage="Password must have at least 8 characters"ControlToValidate="txtPassword">
        </asp:CustomValidator>

        <asp:Label id="lblStatus" runat="server" ></asp:Label>
    </form>
</body>

Output is shown below for server-side validation:

Creating Client-Side Validation Functions

In general, it is best that user are provided with both client-side and server-side validation scripts. As seen for the other ASP.NET validation controls, they use client-side scripting automatically if the browser supports it. Howver, with the CustomValidator  you are responsible for providing any sort of client-side validation.

To add client-side validation for the CustomValidator  control, all you need is to add a client-side scripting function that accepts two parameters, just like the server-side event handler. This function should then be associated with the CustomValidator 's ClientValidationFunction property.