Master ASP.NET Validator Controls

Tightly Control Data Input with Little or No Programming

asp:feature

Languages: VB

Technologies: Validation | Validator Controls | Custom Controls

 

Master ASP.NET Validator Controls

Tightly Control Data Input with Little or No Programming

 

By Steven A. Smith

 

The ASP.NET validator controls make it incredibly easy to add validation logic to forms, which eliminates the need for ASP.NET developers to become experts in client-side JavaScript for most validation tasks. What's more, the ASP.NET validator controls perform their validation on both the client and server (or only on the server, if you wish). That's important because malicious users easily can bypass pure client-side validation. In this article, I'll briefly cover the basics of the validator controls, and then I'll describe some advanced validation techniques. See the end of the article for details about downloading the files used in this article.

 

All of the validator controls (with the exception of the ValidationSummary control) derive from the Label Web control, in the System.Web.UI.WebControls namespace of the .NET Framework. FIGURE 1 displays the class hierarchy of the validator controls. The validator controls inherit from the BaseValidator control. The BaseValidator class cannot be instantiated, but it does define several properties and one method that are common to all of the validator controls.

 


FIGURE 1: Here's the validator controls' class hierarchy. Note how ASP.NET takes advantage of the object-oriented features of the .NET Framework to build powerful controls like the CustomValidator out of simple controls such as the Label, both of which have their roots in the WebControl class.

 

Property

Description

ControlToValidate

The ID of the data entry control that this validator validates.

EnableClientScript

Set to False to perform server-side validation only. The default is True.

ErrorMessage

The message to display when validation fails.

IsValid

True if the ControlToValidate control passes the validation rules.

Text

Displayed when validation fails (instead of ErrorMessage). Often used to display an icon next to a control in conjunction with a ValidationSummary control that displays the ErrorMessage.

Display

Dynamic | None | Static - controls how the validator control is rendered on the HTML page.

Method

Description

Validate

Causes the control to perform its validation checks and is called automatically when a form is submitted.

FIGURE 2: The BaseValidator class defines these properties and methods.

 

You should know a few things about the properties and methods the BaseValidator class defines. First, the ControlToValidate property must be set to the ID of a control on the page, or the ASP.NET page will fail to load. Second, by default, the Text property will be displayed wherever the validator control is located on the page any time IsValid evaluates to False. If the Text property isn't set, the error message will be displayed instead. Many developers use an asterisk for the Text property to mark invalid fields, and then elaborate with a more detailed description of the problem in the ErrorMessage field. Third, ValidatorDisplay can be set to Dynamic, None, or Static. None will make the validator control invisible. When set to Static, ASP.NET reserves space that the error message will occupy even when the validator isn't visible. When set to Dynamic, space isn't reserved when the validator isn't visible. Finally, you can use the Validate method to make a validator control perform its validation checks. The validator controls normally do these checks automatically, though, so you should rarely need this method.

 

The BaseValidator control provides a good solid foundation upon which to build. However, you can't actually instantiate and use a BaseValidator by itself. You need to work its child controls, which include the RequiredFieldValidator, CompareValidator, RangeValidator, RegularExpressionValidator, and CustomValidator, in order of complexity. Finally, the ValidationSummary control, which doesn't inherit from BaseValidator, provides a great way to summarize the results of all the validators on a page in one place. See the sidebar "In Short" for a summary of the validators I'll be exploring in the next section.

 

Common Validators

RequiredFieldValidator. The simplest validator is the RequiredFieldValidator. It only adds one string property, InitialValue, to those of the BaseValidator. RequiredFieldValidator compares the value of a control with its InitialValue property (which defaults to an empty string). If the two are the same, RequiredFieldValidator determines that the value of the control is invalid. The InitialValue property is useful for situations in which the default isn't blank, such as a drop-down list that has as its first value Select an Item. Note, however, that if the InitialValue property is set to something other than an empty string, a blank entry will be considered valid because it differs from InitialValue, which isn't blank. The simplest way to handle both situations is to use two RequiredFieldValidator controls.

 

Here's an example of using a RequiredFieldValidator to require an entry in the Name text-box control:

 

Name:

 

ErrorMessage="Name is required." ControlToValidate="Name" />

 

CompareValidator. You use the CompareValidator to compare a control either to a static value or to the value of another control. The CompareValidator exposes four properties to define how the comparison is performed. The Type property, a variable of type ValidationDataType, is used to describe the type of data expected in the ControlToValidate. The Operator property, of type ValidationCompareOperator, determines what kind of comparison the control should perform and includes options such as LessThan, Equal, and NotEqual. One important option for the Operator property is DataTypeCheck. If set, the CompareValidator control will use this option simply to check that the ControlToValidate property is of the type defined by the Type property.

 

The last two properties exposed by the CompareValidator control are two strings: ControlToCompare, the ID of the comparison control; and ValueToCompare, the static value against which you're comparing. Only one of these can be set for a given instance of a CompareValidator control.

 

The following code illustrates how to use the CompareValidator to validate two dates, one of which must follow the other. The first CompareValidator, StartIsDate, uses the DataTypeCheck operator to verify that the StartDate is of type Date. For this kind of validation, neither ControlToCompare nor ValueToCompare need be set. The second validator, DateCompare, checks to make sure that EndDate is greater than or equal to the StartDate:

 

Start Date:

End Date:

 

ControlToValidate="StartDate" Type="Date"

Operator="DataTypeCheck"

ErrorMessage="StartDate must be a valid date." />

 

ControlToValidate="EndDate" ControlToCompare="StartDate"

ErrorMessage="End Date must be greater than Start Date."

Operator="GreaterThanEqual" Type="Date" />

 

RangeValidator. The RangeValidator control is similar to the CompareValidator, but is simpler. RangeValidator is only used to verify that a control's value falls within a specified range, which you specify with the MaximumValue and MinimumValue properties. It also includes a Type property, just like the CompareValidator. By specifying values for MaximumValue, MinimumValue, or both, it's very easy to validate that a value falls within an allowable range. Note that values are always inclusive. The code here demonstrates a simple use of the RangeValidator:

 

Age:

ControlToValidate="Age"

ErrorMessage="Age must be between 18 and 80."

MaximumValue="80" MinimumValue="18" Type="Integer" />

 

RegularExpressionValidator. Regular expressions are a powerful way of describing a wide variety of string patterns. The RegularExpressionValidator is more complex than the other validators because it requires knowledge of regular expressions, which, to the uninitiated, tend to resemble a series of random keystrokes. Entire books have been devoted to regular expressions and their use, and a large number of common ones are available online at http://RegExLib.com/. This site is a good place to look for common validation expressions, as well. (I manage the site as part of ASPSmith.com.) In this article, I'll describe only a few simple expressions.

 

The RegularExpressionValidator control exposes one string property, ValidationExpression, and uses it to validate the ControlToValidate control. The expression must be a valid regular expression, or the control will throw an exception. Regular expressions use a number of symbols to represent different kinds of string patterns. For example, the ^ symbol represents the beginning of the string to be matched, and the $ symbol represents the end of the string to be matched. For most validation expressions, you'll want the regular expression to begin with ^ and end with $ because you want to validate the entire contents of the ControlToValidate (as opposed to just checking for the existence of a substring within the ControlToValidate control's value).

 

An important character in the regular expression language is the backslash, or \. This symbol is used to prefix other characters to change their meaning. For example, the letter d by itself in an expression normally means the letter d. However, if you prefix it with a backslash, as in \d, then it means "match any numeric digit." Following any expression with a number inside curly braces (e.g., {5}), means that pattern must be repeated a designated number of times. So, to match exactly five numeric digits, such as for a U.S. ZIP code, the following expression could be used: ^\d{5}$.

 

If more than one pattern is valid, you can use the | character between expressions. This has the effect of saying "match this or match that." Building on the previous example, a regular expression that would match a five-digit ZIP code or a nine-digit ZIP+4 code (with hyphen), would be: ^\d{5}$|^\d{5}-\d{4}$. Using this expression, the following code demonstrates how to validate a text box that contains a valid ZIP or ZIP+4 code:

 

ZIP Code:

runat="server"

ErrorMessage="ZIP Code format must be 55555 or 55555-5555."

ControlToValidate="ZIP"

ValidationExpression="^\d{5}$|^\d{5}-\d{4}$" />

 

CustomValidator. When the other validators just can't get the job done, that's when it's time to use the CustomValidator. As its name suggests, this control allows you to define the validation logic yourself, to allow such things as credit-card verification or e-mail Mail Exchanger record look-ups to be performed as part of the validation. The CustomValidator exposes one property, ClientValidationFunction, which you use to designate a client-side function for validation. The CustomValidator also supplies the ServerValidate event, which you use to tie in the server-side validation for the control. When you specify a function name for OnServerValidate, the CustomValidator will use that function to perform its validation on the server.

 

Both the client-side and server-side functions must follow a specific format in order to work with the CustomValidator. The server-side function must be a sub (void in C#) and must take two parameters, an Object argument and a System.Web.UI.WebControls.ServerValidateEventArgs argument. The listing in FIGURE 3 shows an example server-side validation function to check if a form contains a perfect square (a number whose square root is an integer):

 

Protected Sub validateSquare(sender As Object, _

 e As System.Web.UI.WebControls.ServerValidateEventArgs)

   Dim _sqrt As Integer

   Try

      'Get the square root rounded to nearest integer

      _sqrt = Int32.Parse(Math.Round(Math.Sqrt( _

         [Double].Parse(e.Value))).ToString())

      'Compare the rounded square root, squared, with

      'the original value and return true if they are equal.

      e.IsValid = (Int32.Parse(e.Value) = _sqrt * _sqrt)

   Catch

      'Return false if any exceptions occur

      e.IsValid = False

   End Try

End Sub 'validateSquare

FIGURE 3: The server-side validation function for a CustomValidator, the validateSquare method, must take two properties, an object and a ServerValidateEventArgs. The value to be validated is provided in the ServerValidateEventArgs' Value property. After validation, you must set the ServerValidateEventArgs' IsValid property appropriately.

 

This routine, validateSquare, takes the value to be validated (e.Value) and computes the square root of the number, rounded to the nearest integer. Then, the routine sets the e.IsValid property to the result of the comparison of the original value with the square of the rounded square root. For a perfect square, where the square root is an integer, the two values will be equal, and IsValid will be set to True. Otherwise, IsValid is set to False. As an additional measure, if there are any errors converting the value from a string to an integer, the Catch block sets IsValid to False.

 

Although this is a very simple example, you can see how you could add as much complex business logic to this validation function as you need, making CustomValidator a powerful tool. Unfortunately, this function is only called when the form posts back, meaning that it requires a round trip to the Web server for each validation. In order to support client-side validation, the ClientValidationFunction property must be set, and that function must be registered on the page. The following code demonstrates how to add a client script block to an ASP.NET page programmatically:

 

Private Sub Page_Load(sender As Object, e As System.EventArgs)

   Dim validateScript As String = _

      ""

   Page.RegisterClientScriptBlock("validateSquare", validateScript)

End Sub 'Page_Load

 

Here's the HTML generated by ASP.NET to support the client-side validation:

 

 

The following HTML wires up these client- and server-side validation functions. Note the use of both OnServerValidate and ClientValidationFunction:

 

Enter a Perfect Square (the square of an integer)

Display="Dynamic" OnServerValidate="validateSquare"

ControlToValidate="square"

ErrorMessage="Value must be a perfect square."

ClientValidationFunction="isPerfectSquare"/>

 

ValidationSummary. By default, error information is displayed at the location of the validator control. However, displaying verbose error messages like this can play havoc with the layout of the form, and it is often more user-friendly simply to summarize the validation errors found and mark invalid entries somehow. The ValidationSummary control serves as a way to organize all of the validation error messages in one place, usually at the top of the form, so that, at a glance, a user can tell which fields need to be corrected.

 

The ValidationSummary control can be rendered in a variety of formats, as specified by the DisplayMode property. These include a simple list, a bulleted list (the default), or a single paragraph format. Optionally, the summary can be hidden by setting the ShowSummary property to False, and the summary can be displayed in a pop-up message box if the ShowMessageBox property is set to True. Finally, you can use the HeaderText property to add a standard header to the list of validation errors. The listing in FIGURE 4 shows a simple form with three RequiredFieldValidators and a ValidationSummary control. FIGURE 5 shows the output after submitting the form with no completed fields.

 


Name:

 

ErrorMessage="Name is required."

ControlToValidate="Name">*

Rank:

 

ErrorMessage="Rank is required."

ControlToValidate="Rank">WRONG!


Serial Number:

 

runat="server"

ErrorMessage="Serial Number is required." ControlToValidate="Serial">

FIGURE 4: With the addition of a ValidationSummary control to this Web form, the form will display all of the error messages for all of the validator controls at the top of the page so the user easily can see which fields need to be corrected. Note that the text property of each validator control also will appear in place of the validator control if it is invalid (e.g., "*" or "Wrong!").

 


FIGURE 5: After trying to submit the Web form without filling in the required fields, the user is presented with a list of invalid-field error messages in a ValidationSummary control at the top of the form, and each form element has a marker next to it noting that it is invalid.

 

Advanced Validation Techniques

Although the validator controls are a huge step forward compared with what was available in ASP classic, they still require writing a fair bit of code to perform anything but the simplest validation. Validation logic can be combined with other form elements by creating a composite custom control. A custom control is simply a class that inherits from the System.Web.UI.Control class and that has two or more child controls. In this case, the ValidZip control has three child controls: a TextBox, a RequiredFieldValidator, and a RegularExpressionValidator. By programmatically instantiating these controls and then adding them to the Controls collection of your composite control, you can effectively package several Web controls together into one. Then, this composite control can be placed in the toolbox in Visual Studio .NET and can be dragged and dropped onto the design surface of a Web form wherever it is needed. FIGURE 6 shows the code required to create a composite control for encapsulating the validation logic and input control for a U.S. ZIP code.

 

Imports System.Web.UI.WebControls

Imports System.Web

Imports System.Web.UI

 

Public Class ValidZip

    Inherits System.Web.UI.Control

    Implements INamingContainer

    Protected myTextBox As TextBox

    Protected myRequiredValidator As RequiredFieldValidator

    Protected myRegExValidator As RegularExpressionValidator

 

    Protected Overrides Sub CreateChildControls()

        ' Instantiate Controls

 

        ' Create the TextBox

        myTextBox = New TextBox()

        myTextBox.EnableViewState = True

        myTextBox.ID = "myTextBox"

 

        ' Create the required field validator

        myRequiredValidator = New RequiredFieldValidator()

        myRequiredValidator.ID = "myRequiredValidator" + _

         Me.UniqueID

         myRequiredValidator.ControlToValidate = _

         myTextBox.UniqueID

        myRequiredValidator.Display = _

         ValidatorDisplay.Dynamic

        myRequiredValidator.EnableViewState = False

        myRequiredValidator.Text = "*"

        myRequiredValidator.ErrorMessage = _

         "ZIP Code is required."

 

        ' Create the regular expression validator(s)

        myRegExValidator = New RegularExpressionValidator()

        myRegExValidator.ID = "myRegExValidator" + _

         Me.UniqueID

        myRegExValidator.ControlToValidate = _

         myTextBox.UniqueID

        myRegExValidator.Display = ValidatorDisplay.Dynamic

        myRegExValidator.EnableViewState = False

        myRegExValidator.Text = "*"

        myRegExValidator.ErrorMessage = _

          "ZIP code invalid.   Must either be 5 digits " & _

         "or 5 digits, a hyphen, and 4 digits."

        myRegExValidator.ValidationExpression = _

         "^\d{5}$|^\d{5}-\d{4}$"

 

        Me.Controls.Clear()

        Me.Controls.Add(myTextBox)

         Me.Controls.Add(myRequiredValidator)

        Me.Controls.Add(myRegExValidator)

    End Sub

End Class

FIGURE 6: The ValidZip composite control combines three other Web controls (a TextBox, a RequiredFieldValidator, and a RegularExpressionValidator) into a single control that can be managed more easily and can be reused across many Web forms.

 

To use this control, you must add a reference to the top of the aspx page, and then reference the control just like any other Web control, using a prefix and the name of the control. FIGURE 7 shows a complete ASP.NET page using this control.

 

<%@ Page language="c#" %>

<%@ Register TagPrefix="cc1"

 Namespace="CompositeValidationControls"

 Assembly="ValidZip" %>

 "-//W3C//DTD HTML 4.0 Transitional//EN" >

  

    ValidZip

  

  

    

      

      

        ZIP:

        

        

      

        

        

    

  

FIGURE 7: Using ValidZip in an ASP.NET page is as simple as adding the control to the page and ensuring the control is registered, using the <%@ Register %> page directive. Note that the ValidZip control includes both the input (TextBox) and the validation logic, greatly reducing the number of controls needed to build this form.

 

You can expand upon this technique and apply it to many different common form elements, such as e-mail addresses, phone numbers, and credit-card numbers.

 

Finally, one last technique to be aware of is the use of the Page.IsValid property, which is set on any ASP.NET page that uses validator controls. After a post-back, this property will be set to True only if the page passed all of its validation tests. Thus, before performing business logic that depends on valid data, you should test this property to verify the page's data has passed all validation tests. You can do this quite simply, with an If Page.IsValid Then statement.

 

Limitations

One limitation of the validator controls that ship with ASP.NET is that they are completely tied to the user-interface layer of an application. This is because they inherit from the System.Web.UI.WebControls.Label class, a class that's only useful within the scope of the user-interface layer. I've been in situations in which I've developed complex validation logic using the standard validator controls, only to realize I was unable to reuse any of it when I wanted to import data using a batch file or a Web Service. I'm working on an advanced validation class that would solve this limitation. If you have questions or ideas about how to implement such a solution, please contact me so we can share our ideas. With any luck, this functionality will be built into a future version of the .NET Framework.

 

The validator controls that ship with ASP.NET provide easy Web form validation that was unavailable to ASP classic developers. These controls eliminate the need for Web form developers to write validation code, especially client-side script, for most simple validation rules. Regular expressions provide a powerful way to match many kinds of string patterns, and you can use custom validation routines to handle complex validation logic that goes beyond string or number comparisons. Finally, commonly validated data fields can be packaged into composite controls that can be dragged and dropped as needed onto Web forms, to provide encapsulation and reuse of validation rules across different Web forms.

 

The files referenced in this article are available for download.

 

Steven A. Smith is president of ASPAlliance.com, a popular resource for the ASP and ASP.NET developer community. He also conducts training for ASPSmith.com. Steven is the author of ASP.NET By Example, a beginner's ASP.NET book full of working examples that can be viewed live at the book's Web site (http://aspauthors.com/aspnetbyexample/). Readers may reach Steven at mailto:[email protected].

 

In Short

Here's a quick overview of the available validator controls, what they do, and how to use them.

 

RequiredFieldValidator - Use this validator for any field that is required. It must be used for any required field in addition to other validator controls because this is the only validator that can determine when its ControlToValidate has a blank value.

 

CompareValidator - Use this validator to compare a field with a single fixed value or another control's value, by specifying a ValueToCompare or a ControlToCompare (but not both). Specify the kind of comparison to perform and data type of the control by setting the ValidationCompareOperator and ValidationDataType properties. This is also useful for validating that a value is a particular data type.

 

RangeValidator - Use this validator to specify that a value must fall within a particular range of values.   RangeValidator supports the MinimumValue and MaximumValue properties in addition to a ValidationDataType property.

 

RegularExpressionValidator - Ensure user input matches one or more defined patterns using regular expressions and this validator. Set the regular expression that must match the ControlToValidate's value in this control's ValidationExpression property.

 

CustomValidator - When none of the above can do the job, write your own validation logic and wrap it up in a CustomValidator. Specify client-side validation functions with the ClientValidationFunction and wire up server-side validation by handling the ServerValidate event.

 

ValidationSummary - Displays a summary of all error messages on a page, either in HTML on the page itself, in a message box, or both. Specify its format by settings its DisplayMode property. Provide header text and specify the color of the text using the HeaderText and ForeColor properties, respectively. Toggle display of HTML results and message-box results by setting the ShowSummary and ShowMessageBox properties. Finally, designate whether the control should be updated using client-side script by setting its EnableClientScript property.

 

 

Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish