Validation Controls

Validation Controls

Six of the controls found in System.Web.UI.WebControls are provided to help you validate user input in Web forms. Known as validation controls, or simply validators, these controls are some of the most interesting and potentially useful of all the controls in ASP.NET. Here are two reasons why:

  • Validation checking for example, verifying that a required field isn t blank or a date selected by the user falls within a specified range is a common requirement in Web applications.

  • ASP.NET s validation controls are smart. They do their checking on both the client and the server. Validation controls emit JavaScript that executes in the browser and prevents postbacks from occurring if a page contains invalid input. And after a postback occurs, validators check the input again on the server.

Why do validation controls recheck the input on the server? One, rechecking prevents spoofing. Two, it enables the input to undergo a validation check even if it originated from a browser that doesn t support client-side scripting.

Validating user input on the client side is a Good Thing because it prevents postbacks from occurring that would ultimately be rejected by the server anyway. Checking on the client side is nothing new; Web programmers have been doing it for years. Unfortunately, writing client-side validation scripts requires a non-trivial knowledge of Dynamic HTML and client-side scripting. Validation controls lower the barrier to entry by encapsulating the required logic in easy-to-use classes. You simply attach validators to the controls you want to validate, and the validators do the rest.

What kinds of checks are validation controls capable of performing? For starters, they can verify that

  • An input field isn t blank (RequiredFieldValidator)

  • An input value falls within a specified range (RangeValidator)

  • An input string conforms to a pattern matching a regular expression (RegularExpressionValidator)

  • An input value is equal to, not equal to, less than, equal to or less than, greater than, or greater than or equal to either a specified value or another input value (CompareValidator)

If none of these validation types fit the bill, you can use a CustomValidator control to enact validation routines of your own. And the ValidationSummary control enables error messages provided by other validators to be displayed as a group.

One nuance you should be aware of regarding validator controls is that the client-side validation code they emit doesn t work with all browsers. The JavaScript that they return makes extensive use of the browser s DHTML document object model (DOM). Before the W3C standardized the DOM, Internet Explorer and Netscape Navigator implemented incompatible DOMs. Client-side validation works fine in Internet Explorer 4 and later. ASP.NET sniffs out the browser type and doesn t even attempt to return client-side validation code to Navigator.

The good news is that the incompatibilities affect only client-side validation. Server-side validation works regardless of the browser type, so someone using a down-level browser won t be able to submit invalid data without you knowing about it. They will, however, incur a round trip to the server and back each time they try.

Using the Validation Controls

All validator control classes with the exception of ValidationSummary derive from a common base class BaseValidator and therefore share many traits, including the following:

  • All feature a property named ControlToValidate that identifies the control whose input the validator validates.

  • All have a property named ErrorMessage that defines the error message the control displays if it deems an input invalid. Where on the Web page the error message appears depends on where on the page the validator is located. Position the validator to the right of a TextBox control, for example, and the validator s error message appears to the right of the TextBox, too.

  • All have a property named ForeColor that specifies the color in which error messages are rendered. The default is red.

  • All have a property named Display that determines how a validator s error message is displayed. Display can be set to Static, which statically reserves space in the Web page for the error message; Dynamic, which doesn t reserve space for the error message (and therefore might alter the page layout if the validator fires); and None, which prevents the error message from displaying at all. Use the None option when you intend to display the validators error messages in a ValidationSummary control.

  • All have a property named EnableClientScript that allows client-side validation to be selectively enabled or disabled. EnableClientScript defaults to true. Setting it to false prevents the control from emitting client-side JavaScript and therefore disables client-side error checking. Checks are still performed on the server, however.

Here s an example demonstrating how some of these properties are used. The following code declares a TextBox and attaches a RequiredFieldValidator to it. It also specifies the error message displayed if the validator fires, ensures that space is reserved for the error message even if it isn t displayed (possibly preventing the page layout from changing if the error message does appear), and sets the error message s color to blue:

<asp:TextBox  TextMode="Password" RunAt="server" /> <asp:RequiredFieldValidator ControlToValidate="Password" ErrorMessage="Required field" Display="static" ForeColor="blue" RunAt="server" />

If you d prefer, you can omit the ErrorMessage attribute and place the error message between the validator s start and end tags:

<asp:RequiredFieldValidator ControlToValidate="Password" Display="static" ForeColor="blue" RunAt="server" > Required Field </asp:RequiredFieldValidator>

The downside to defining an error message this way is that it prevents the error message from working in conjunction with ValidationSummary controls. The upside is that it lets you create rich error messages that include HTML tags.

A validator can be attached to only one control, but any number of validator controls can be declared on a page. In addition, a given control can have several validators attached to it. The following example combines a RequiredFieldValidator and a RegularExpressionValidator to verify that a password field isn t blank and that it contains at least eight characters:

<asp:TextBox  TextMode="Password" RunAt="server" /> <asp:RequiredFieldValidator ControlToValidate="Password" ErrorMessage="Required field" Display="dynamic" ForeColor="blue" RunAt="server" /> <asp:RegularExpressionValidator ControlToValidate="Password" ValidationExpression=".{8,}" ErrorMessage="You must enter at least 8 characters" Display="dynamic" ForeColor="blue" RunAt="server" />

At first glance, it might seem as if the RequiredFieldValidator is superfluous because the RegularExpressionValidator verifies that the TextBox contains at least eight characters. However, RegularExpressionValidator performs validation checks only on nonblank fields. The same is true of other validators as well. Therefore, if you want to verify that an input field isn t blank and that it meets other validation criteria too, you must combine RequiredFieldValidator with other validation controls.

In the preceding example, note that the validators Display properties are set to Dynamic rather than Static. The reason? If you write Display= static, the RegularExpressionValidator s error message, if displayed, appears far to the right of the TextBox because of the space reserved for the RequiredFieldValidator s error message. Display= dynamic prevents either control from claiming space that might be used by the other and therefore enables either error message to appear in the same place.

RequiredFieldValidator

As I mentioned, the RequiredFieldValidator control validates input by verifying that the corresponding field isn t blank. It s perfect for TextBox controls representing required fields in a form because if any of those TextBoxes is blank, the RequiredFieldValidator won t allow the form to be submitted to the server.

Here s an example that verifies that a TextBox named EMail isn t blank:

<asp:TextBox  RunAt="server" /> <asp:RequiredFieldValidator ControlToValidate="EMail" ErrorMessage="Required field" Display="static" RunAt="server" />

Because required fields are so common in Web forms, RequiredFieldValidator has the potential to see more use than all the other validation controls combined. It s often used in conjunction with other validation controls because none of the others run their validation checks on blank fields.

RangeValidator

The RangeValidator control is the answer to the question, How do I ensure that an input value falls within a specified range? Suppose you ask the user to type in a percentage and that valid values range from 0 to 100, inclusive. Here s how to reject any numbers that fall outside that range:

<asp:TextBox  RunAt="server" /> <asp:RangeValidator ControlToValidate="Percent" MinimumValue="0" MaximumValue="100" Type="Integer" ErrorMessage="Value out of range" Display="static" RunAt="server" />

The Type attribute tells a RangeValidator what type of data to use in the comparison. If you don t specify a type, Type defaults to String. Type= Integer performs a numeric comparison involving integers. Other valid Type attributes include Currency, Date, and Double. The following example displays an error message if the date typed into a TextBox doesn t fall in the fourth quarter of 2002:

<asp:TextBox  RunAt="server" /> <asp:RangeValidator ControlToValidate="MyDate" MinimumValue="10/01/2002" MaximumValue="12/31/2002" Type="Date" ErrorMessage="Date out of range" Display="static" RunAt="server" />

In practice, checking a range of dates with RangeValidator is of limited usefulness because well-designed sites permit users to pick dates from a calendar. Manually entered dates are problematic because they re culture-sensitive (many parts of the world put days before months, for example) and because RangeValidator understands a limited set of date formats.

CompareValidator

The CompareValidator control validates input by comparing it to a constant value specified with a ValueToCompare attribute or to a value in another control identified with a ControlToCompare attribute. ControlToCompare makes CompareValidator a valuable control for validating input based on other input.

Suppose you invite the user to enter minimum and maximum values denoting the ends of a range. It doesn t make sense to accept a maximum that s less than the minimum, so you could use a CompareValidator to ensure the integrity of the input. In the following example, the validator signals an error if the maximum is less than the minimum. The Operator attribute specifies that the value entered in the TextBox named Maximum must be equal to or greater than the value entered in the TextBox named Minimum. The Type attribute identifies the type of data involved in the comparison:

<asp:TextBox  RunAt="server" /> <asp:TextBox  RunAt="server" /> <asp:CompareValidator ControlToValidate="Maximum" ControlToCompare="Minimum" Type="Integer" Operator="GreaterThanEqual" ErrorMessage="Invalid maximum" Display="static" RunAt="server" />

Other supported values for Operator are Equal, NotEqual, GreaterThan, Less Than, LessThanEqual, and DataTypeCheck. The last of these values validates the type of data entered by verifying that it matches the type specified in the Type attribute. If you simply wanted to verify that the user input an integer, for example, you could set Type to Integer and Operator to DataTypeCheck.

Another use for CompareValidator is to compare two passwords on pages that ask the user to enter a password and then enter it again to validate the first. Here s the code to compare two passwords:

<asp:TextBox  TextMode="Password" RunAt="server" /> <asp:TextBox  TextMode="Password" RunAt="server" /> <asp:CompareValidator ControlToValidate="Password2" ControlToCompare="Password1" Type="String" Operator="Equal" ErrorMessage="Mismatch" Display="static" RunAt="server" />

In scenarios like this one, it s important to validate the second of the two inputs rather than the first to prevent the CompareValidator from firing when the focus moves from the first TextBox to the second.

Be aware that string comparisons performed by CompareValidator are case-sensitive. With passwords that s typically what you want, but for some forms of text input, you might not want the comparison to be case-sensitive.

RegularExpressionValidator

The most versatile validation control by far is the RegularExpressionValidator, which validates input by verifying that it conforms to a format specified in a regular expression. You can use a RegularExpressionValidator to perform a variety of common validation chores, from verifying that an input value contains only numbers to ensuring that e-mail addresses, zip codes, and credit card numbers are well formed.

Here s a very simple example one that uses a RegularExpressionValidator to reject input containing nonnumeric characters:

<asp:TextBox  RunAt="server" /> <asp:RegularExpressionValidator ControlToValidate="Quantity" ValidationExpression="^\d+$" ErrorMessage="Digits only" Display="static" RunAt="server" />

In a regular expression, \d represents the digits 0 9 and + means one or more of. The expression \d+ means one or more characters that are digits. If the user tries to slip in a string with a letter in it, the validator will reject it.

The next example validates an e-mail address. It can t actually verify that the address is valid, but it can (and does) verify that the address is well formed:

<asp:TextBox  RunAt="server" /> <asp:RegularExpressionValidator ControlToValidate="EMail" ValidationExpression="^[\w\.-]+@[\w-]+\.[\w\.-]+$" ErrorMessage="Invalid e-mail address" Display="static" RunAt="server" />

Let s dissect the regular expression. ^ means start at the beginning of the string. That s important because otherwise a string with a substring matching the regular expression (for example, !@#$%^&* name@domain.com ) would fool the validator into validating the input. The same goes for the $ at the end: it prevents name@domain.com !@#$%^&* from resulting in a false match. [\w\.-]+ means one or more of the following characters: letters, numbers, underscores, periods, and hyphens. @ means the characters must be followed by an @ sign. [\w-]+ indicates that the @ sign must be followed by one or more letters, numbers, underscores, or hyphens, and \. means all that must be followed by a period. Finally, [\w\.-]+ stipulates that the string must end with one or more letters, numbers, underscores, or hyphens. Strings such as jeffpro@wintellect.com and jeff.pro@win-tellect.com pass the test just fine, but jeffpro, jeffpro@wintellect, and jeffpro@**&&^^%%.com do not.

CustomValidator

When none of the other validators fits the bill, CustomValidator will do the job that no others can. As its name implies, CustomValidator validates input using an algorithm that you supply. If you want CustomValidator to check input on the client side, you provide a JavaScript function to do the checking and identify the function with a ClientValidationFunction attribute. (You can use VBScript if you d like, but realize that doing so sacrifices compatibility with browsers other than Internet Explorer. Future versions of ASP.NET will probably support client-side validation in selected third-party browsers.) If you want the input checked on the server as well, you provide the validation method and identify it with an OnServerValidate attribute. The following example uses CustomValidator to verify that an input value is an even multiple of 10:

<asp:TextBox  RunAt="server" /> <asp:CustomValidator ControlToValidate="Amount" ClientValidationFunction="__validateAmount" OnServerValidate="ValidateAmount" ErrorMessage="Amount must be a multiple of 10" Display="static" RunAt="server" /> . . . <script language="JavaScript"> <!-- function __validateAmount (source, args) { args.IsValid = (args.Value % 10 == 0); } --> </script> <script language="C#" runat="server"> void ValidateAmount (Object sender, ServerValidateEventArgs e) { try { e.IsValid = (Convert.ToInt32 (e.Value) % 10 == 0); } catch (FormatException) { // In case a non-numeric value is entered e.IsValid = false; } } </script>

The key is to set args.IsValid to true or false on the client side and e.IsValid to true or false on the server side to indicate whether the input is valid. CustomValidator can be used to apply any validation algorithm you want as long as you re willing to write the code to back it up.

ValidationSummary

ValidationSummary is a different sort of validation control. It doesn t perform any validation of its own. It does, however, offer an alternative method for displaying other validators error messages by batching them up and displaying them as a group. The following example uses a ValidationSummary control to summarize all the validation errors encountered on the page. Note that the other validator controls Display attributes are set to None, which prevents them from displaying error messages on their own. Before the page is submitted to the server, the ValidationSummary control checks the other validators. If any of the validation checks failed, the ValidationSummary control displays the corresponding error messages in a bulleted list:

<asp:TextBox  RunAt="server" /> <asp:RequiredFieldValidator ControlToValidate="UserName" ErrorMessage="The user name can't be blank" Display="none" RunAt="server" /> <asp:TextBox  TextMode="Password" RunAt="server" /> <asp:RequiredFieldValidator ControlToValidate="Password" ErrorMessage="The password can't be blank" Display="none" RunAt="server" /> <asp:RegularExpressionValidator ControlToValidate="Password" ValidationExpression=".{8,}" Display="none" ErrorMessage="The password must contain at least 8 characters" RunAt="server" /> <asp:ValidationSummary DisplayMode="BulletList" HeaderText="This page contains the following errors" RunAt="server" />

The ValidationSummary control s DisplayMode attribute can be set to BulletList, which displays error messages in a bulleted list; List, which displays error messages in a list without bullets; or SingleParagraph, which displays error messages without bullets or line breaks. HeaderText specifies the text, if any, that appears above the error messages.

A ValidationSummary control s ShowMessageBox and ShowSummary properties can be used to further customize the control s output. By default, ShowMessageBox is false and ShowSummary is true, meaning that error messages are displayed in the Web page. However, setting ShowMessageBox to true and ShowSummary to false displays the error messages in a pop-up message box (what JavaScript programmers refer to as an alert box because of the JavaScript command used to display it: alert):

<asp:ValidationSummary DisplayMode="BulletList" HeaderText="This page contains the following errors" ShowMessageBox="true" ShowSummary="false" RunAt="server" />

Setting both ShowMessageBox and ShowSummary to true causes the validation summary to appear in a message box and in the Web page. (Talk about getting someone s attention!)

Spammers, Incorporated

Ever been spammed? Just in case you don t get enough spam already, the application in Figure 6-21 displays a form from a fictitious company named Spammers, Inc., that invites users to enter a name, e-mail address, and other personal information and receive spam in return. It collects most of its input from TextBox controls and validates the input using an assortment of RequiredFieldValidators and RegularExpressionValidators. Specifically, it uses the following validators:

  • RequiredFieldValidators to verify that a name and e-mail address are provided

  • A RegularExpressionValidator to verify that the e-mail address is well formed

  • A RegularExpressionValidator to verify that the zip code, if entered, consists of five numeric characters, optionally followed by a hyphen and four more numeric characters

  • A RegularExpressionValidator to verify that the credit card number, if entered, is well formed specifically, that it contains from 15 to 20 characters and that all characters are either digits or hyphens

Figure 6-20 shows the Spammers, Inc., home page after several validators have fired.

Figure 6-20

The Spammers, Inc., home page.

An item of interest concerning SpammersInc.aspx s implementation is that the OnSignMeUp method, which executes on the server when the Sign Me Up button is clicked, does nothing if IsValid is false:

void OnSignMeUp (Object sender, EventArgs e) { if (IsValid) { ... } }

IsValid is a System.Web.UI.Page property. When the client is Internet Explorer 4 or later, checking IsValid is redundant unless you re concerned about someone intentionally circumventing the client-side script in order to submit invalid data. When the client is any other browser (particularly Netscape Navigator), checking IsValid is essential if you want input to be validated. Validation controls don t do any input checking on the client side in those browsers, so if you fail to check IsValid on the server side, bad input can slip by undetected. IsValid is set to false on the server if any of the page s validation controls flags an error. An IsValid value equal to true means all of the page s input conforms to the criteria specified by the validators. If you want validation controls to work regardless of browser type, always check the page s IsValid property on the server side just in case the input wasn t validated on the client side.

SpammersInc.aspx

<html> <head> <style> <!-- body { font: 10pt verdana }; table { font: 10pt verdana }; input { font: 10pt verdana }; --> </style> </head> <body> <table cellpadding="4" border="1"> <tr bgcolor="yellow"> <td> Hi! We're Spammers, Incorporated. If you'll provide us with an e-mail address, we'll clog your inbox with email. Leave a snail mail address and we'll bombard you with paper mail, too. If you're a totally trusting person, type in a       credit card number. We'll use it to defray office costs next month.

 </td> </tr> </table> <h3>Yes, I want to be spammed. Sign me up now!</h3> <form runat="server"> <table cellpadding="4"> <tr> <td align="right"> Name </td> <td> <asp:TextBox  RunAt="server" /> </td> <td> <asp:RequiredFieldValidator ControlToValidate="Name" ErrorMessage="Please enter your name" Display="dynamic" RunAt="server" /> </td> </tr> <tr> <td align="right"> E-Mail Address </td> <td> <asp:TextBox  RunAt="server" /> </td> <td> <asp:RequiredFieldValidator ControlToValidate="EMail" ErrorMessage="Please enter your e-mail address" Display="dynamic" RunAt="server" /> <asp:RegularExpressionValidator ControlToValidate="EMail" ValidationExpression="^[\w\.-]+@[\w-]+\.[\w\.-]+$" ErrorMessage="Invalid e-mail address" Display="dynamic" RunAt="server" /> </td> </tr> <tr> <td align="right"> Address </td> <td> <asp:TextBox  RunAt="server" /> </td> <td> </td> </tr> <tr> <td align="right"> City </td> <td> <asp:TextBox  RunAt="server" /> </td> <td> </td> </tr> <tr> <td align="right"> State </td> <td> <asp:DropDownList  RunAt="server"> <asp:ListItem Text="AL" RunAt="server" /> <asp:ListItem Text="AK" RunAt="server" /> <asp:ListItem Text="AR" RunAt="server" /> <asp:ListItem Text="AZ" RunAt="server" /> <asp:ListItem Text="CA" RunAt="server" /> <asp:ListItem Text="CO" RunAt="server" /> <asp:ListItem Text="CT" RunAt="server" /> <asp:ListItem Text="DC" RunAt="server" /> <asp:ListItem Text="DE" RunAt="server" /> <asp:ListItem Text="FL" RunAt="server" /> <asp:ListItem Text="GA" RunAt="server" /> <asp:ListItem Text="HI" RunAt="server" /> <asp:ListItem Text="IA" RunAt="server" /> <asp:ListItem Text="ID" RunAt="server" /> <asp:ListItem Text="IL" RunAt="server" /> <asp:ListItem Text="IN" RunAt="server" /> <asp:ListItem Text="KS" RunAt="server" /> <asp:ListItem Text="KY" RunAt="server" /> <asp:ListItem Text="LA" RunAt="server" /> <asp:ListItem Text="MA" RunAt="server" /> <asp:ListItem Text="MD" RunAt="server" /> <asp:ListItem Text="ME" RunAt="server" /> <asp:ListItem Text="MI" RunAt="server" /> <asp:ListItem Text="MN" RunAt="server" /> <asp:ListItem Text="MO" RunAt="server" /> <asp:ListItem Text="MS" RunAt="server" /> <asp:ListItem Text="MT" RunAt="server" /> <asp:ListItem Text="NC" RunAt="server" /> <asp:ListItem Text="ND" RunAt="server" /> <asp:ListItem Text="NE" RunAt="server" /> <asp:ListItem Text="NH" RunAt="server" /> <asp:ListItem Text="NJ" RunAt="server" /> <asp:ListItem Text="NM" RunAt="server" /> <asp:ListItem Text="NV" RunAt="server" /> <asp:ListItem Text="NY" RunAt="server" /> <asp:ListItem Text="OH" RunAt="server" /> <asp:ListItem Text="OK" RunAt="server" /> <asp:ListItem Text="OR" RunAt="server" /> <asp:ListItem Text="PA" RunAt="server" /> <asp:ListItem Text="RI" RunAt="server" /> <asp:ListItem Text="SC" RunAt="server" /> <asp:ListItem Text="SD" RunAt="server" /> <asp:ListItem Text="TN" RunAt="server" /> <asp:ListItem Text="TX" RunAt="server" /> <asp:ListItem Text="UT" RunAt="server" /> <asp:ListItem Text="VA" RunAt="server" /> <asp:ListItem Text="VT" RunAt="server" /> <asp:ListItem Text="WA" RunAt="server" /> <asp:ListItem Text="WI" RunAt="server" /> <asp:ListItem Text="WV" RunAt="server" /> <asp:ListItem Text="WY" RunAt="server" /> </asp:DropDownList> </td> <td> </td> </tr> <tr> <td align="right"> Zip </td> <td> <asp:TextBox  RunAt="server" /> </td> <td> <asp:RegularExpressionValidator ControlToValidate="ZipCode" ValidationExpression="^(\d{5} \d{5}\-\d{4})$" ErrorMessage="Invalid zip code" Display="dynamic" RunAt="server" /> </td> </tr> <tr> <td align="right"> Credit Card Number </td> <td> <asp:TextBox  RunAt="server" /> </td> <td> <asp:RegularExpressionValidator ControlToValidate="CreditCardNumber" ValidationExpression="^[\d\-]{15,20}$" ErrorMessage="Invalid card number" Display="dynamic" RunAt="server" /> </td> </tr> <tr> <td> </td> <td> <asp:Button Text="Sign Me Up" OnClick="OnSignMeUp" RunAt="server" /> </td> <td> </td> </tr> </table> </form> </body> </html> <script language="C#" runat="server"> void OnSignMeUp (Object sender, EventArgs e) { if (IsValid) { StringBuilder sb = new StringBuilder ("Thanks.aspx?Name=", 256); sb.Append (Name.Text); sb.Append ("&EMail="); sb.Append (EMail.Text); string address = Address.Text; string city = City.Text; string state = StateList.SelectedItem.Text; string zip = ZipCode.Text; if (address.Length > 0 && city.Length > 0 && zip.Length > 0) { sb.Append ("&Address="); sb.Append (address); sb.Append ("&City="); sb.Append (city); sb.Append ("&State="); sb.Append (state); sb.Append ("&ZipCode="); sb.Append (zip); } string number = CreditCardNumber.Text; if (number.Length > 0) { sb.Append ("&CreditCardNumber="); sb.Append (number); } Response.Redirect (sb.ToString ()); } } </script>

Figure 6-21

Source code for Spammers, Inc.

Thanks.aspx

<%@ Page Language="C#" %> <html> <body> Here's the information you entered:<br><br> <ul> <% Response.Write ("<li>Name: " + Request["Name"]); Response.Write ("<li>E-mail address: " + Request["EMail"]); if (Request["Address"] != null) { StringBuilder sb = new StringBuilder ("<li>Address: ", 64); sb.Append (Request["Address"]); sb.Append (", "); sb.Append (Request["City"]); sb.Append (", "); sb.Append (Request["State"]); sb.Append (" "); sb.Append (Request["ZipCode"]); Response.Write (sb.ToString ()); } if (Request["CreditCardNumber"] != null) Response.Write ("<li>Credit card number: " + Request["CreditCardNumber"]); %> </ul> Thanks for signing up with Spammers, Inc.! </body> </html>

Connecting Web Forms with Response.Redirect

In addition to showing validators at work, Spammers, Inc., demonstrates another important technique for programming Web forms: how to transfer control from one page to another and transmit data in the process. The application contains not one, but two Web forms: SpammersInc.aspx and Thanks.aspx. When the user clicks the Sign Me Up button, SpammersInc.aspx uses Response.Redirect to transfer control to Thanks.aspx, which displays a summary of the user input along with a thank you (Figure 6-22).

How is the input transmitted to Thanks.aspx? SpammersInc.aspx appends it to the URL in the form of a query string. For example, if the user types Jeff in the name field and jeffpro@wintellect.com in the e-mail address field, Response.Redirect is passed the following URL:

Thanks.aspx?Name=Jeff&EMail=jeffpro@wintellect.com

Thanks.aspx extracts the data from the query string using the ASP.NET Request object and writes it to the HTTP response using Response.Write:

Response.Write ("<li>Name: " + Request["Name"]); Response.Write ("<li>E-mail address: " + Request["EMail"]);

The names used to retrieve data from the Response object must match the parameter names used in the query string. Code that relies on Request and Response objects looks more like ASP code than ASP.NET code, but this is nonetheless an efficient and extremely common technique for moving between pages in ASP.NET.

Figure 6-22

The Spammers, Inc., thank you page.

The StringBuilder Class

To formulate the URL passed to Response.Redirect, SpammersInc.aspx uses a StringBuilder object. StringBuilder is defined in the FCL s System.Text namespace; it provides an efficient and easy-to-use mechanism for building strings on the fly.

Strings in managed applications are instances of System.String, but System.Strings are immutable, meaning once defined, they can t be changed. The following code works but is inefficient because each concatenation operation results in a memory allocation and a memory copy:

string s = ""; for (int i=1; i<=99; i++) { s += i.ToString (); s += ", "; }

The following code produces the same string, but it does so in a fraction of the time. Why? Because it builds the string in a buffer large enough to hold 512 characters:

StringBuilder sb = new StringBuilder (512); for (int i=1; i<=99; i++) { sb.Append (i.ToString ()); sb.Append (", "); } string s = sb.ToString ();

StringBuilder.Append will enlarge the buffer if necessary, but if you know approximately how long the string will be before you start, you can size the buffer accordingly and keep new memory allocations to a minimum.

Building URLs with StringBuilder.Append is a performance optimization. Thanks.aspx also uses StringBuilder to build strings dynamically not to build URLs, but to build the address that it outputs to the page. A few milliseconds per request might not seem like much, but if your application receives thousands of requests per second, a little can add up to a lot.

Conditional Validation

The vast majority of the time, input validation is unconditional. An e-mail address that needs validating one time needs it every time. But occasionally the need arises to validate conditionally usually based on the state of something else on the page, such as a check box. For example, you might want to validate an e-mail address only if a check box labeled E-mail my confirmation is checked.

The Web page in Figures 6-23 and 6-24 demonstrates how to enact conditional validation. In this example, the user is invited to enter his or her name for the purpose of registering a product. The user can optionally enter an e-mail address and check a box to have a confirmation e-mailed. If the box is checked, the e-mail address is validated using a RequiredFieldValidator and a RegularExpressionValidator. If the box isn t checked, validation is skipped even if the user enters something into the e-mail field.

Notice the Enabled= false attributes in the tags that declare the validators. Enabled is a property that validators inherit from System.Web.UI.WebControls.WebControl. It defaults to true, meaning the validator will work as normal. Setting Enabled to false disables the validator and prevents it from performing its validation checks.

Now look at the <asp:CheckBox> tag. It sets AutoPostBack to true, forcing a postback to occur any time the check box is clicked. It also registers a handler OnCheckBoxClicked for the CheckedChanged event that fires each time the check box is clicked. OnCheckBoxClicked enables or disables the validators based on the state of the check box. It enables them if the box is checked and disables them if it s not. Here s the relevant code:

EMailRequiredValidator.Enabled = Confirm.Checked; EMailExpressionValidator.Enabled = Confirm.Checked;

EMailRequiredValidator and EMailExpressionValidator are the validators programmatic IDs; Confirm is the CheckBox ID. By enabling the validators only when the check box is checked, ConditionalValidate.aspx prevents the validators from firing if the input from the control they re attached to is meaningless.

Figure 6-23

The ConditionalValidate application.

ConditionalValidate.aspx

<html> <body> <h1>Conditional Validation Demo</h1> <hr> <form runat="server"> <table cellpadding="4"> <tr> <td align="right"> Name </td> <td> <asp:TextBox  RunAt="server" /> </td> <td> <asp:RequiredFieldValidator ControlToValidate="Name" ErrorMessage="Please enter your name" Display="dynamic" Color="red" RunAt="server" /> </td> </tr> <tr>

 <td align="right"> E-Mail Address </td> <td> <asp:TextBox  RunAt="server" /> </td> <td> <asp:RequiredFieldValidator ControlToValidate="EMail" ErrorMessage="Please enter your e-mail address" Display="dynamic" Color="red" Enabled="false" RunAt="server" /> <asp:RegularExpressionValidator ControlToValidate="EMail" ValidationExpression="^[\w\.-]+@[\w-]+\.[\w\.-]+$" ErrorMessage="Invalid e-mail address" Display="dynamic" Color="red" Enabled="false" RunAt="server" /> </td> </tr> <tr> <td> </td> <td> <asp:CheckBox Text="E-mail my confirmation" OnCheckedChanged="OnCheckBoxClicked" AutoPostBack="true" RunAt="server" /> </td> <td> </td> </tr> <tr> <td> </td> <td> <asp:Button Text="Register" OnClick="OnRegister" RunAt="server" /> </td> <td> </td> </tr> </table> <br><hr><br> <asp:Label  RunAt="server" /> </form> </body> </html> <script language="C#" runat="server"> void OnCheckBoxClicked (Object sender, EventArgs e) { EMailRequiredValidator.Enabled = Confirm.Checked; EMailExpressionValidator.Enabled = Confirm.Checked; } void OnRegister (Object sender, EventArgs e) { if (IsValid) { if (Confirm.Checked) { Output.Text =  "Confirmation will be e-mailed to " + EMail.Text + "."; } else { Output.Text =  "At your request, no confirmation will " +  "be sent."; } } } </script>

Figure 6-24

Conditional input validation.



Programming Microsoft  .NET
Applied MicrosoftNET Framework Programming in Microsoft Visual BasicNET
ISBN: B000MUD834
EAN: N/A
Year: 2002
Pages: 101

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net