WHAT’S IN THIS CHAPTER?
WROX.COM CODE DOWNLOADS FOR THIS CHAPTER
Please note that all the code examples in this chapter are available as a part of this chapter’s code download on the book’s website at www.wrox.com.
When you look at the Toolbox window in Visual Studio 2012 — especially if you’ve read Chapters 4 and 5, which cover the various server controls at your disposal — you may be struck by the number of server controls that come with ASP.NET 4.5. This chapter takes a look at a specific type of server control you find in the Toolbox window: the validation server control.
Validation server controls are a series of controls that enable you to work with the information your end users input into the form elements of the applications you build. These controls work to ensure the validity of the data being placed in the form.
Before you learn how to use these controls, however, this chapter first takes a look at the process of validation.
Developers have been constructing web applications for a number of years. Usually the motivation is to provide or gather information. In this chapter, you focus on the information-gathering and validation aspects of web applications. If you collect data with your applications, collecting valid data should be important to you. If the information isn’t valid, there really isn’t much point in collecting it.
Validation is a set of rules that you apply to the data you collect. These rules can be many or few and enforced either strictly or in a lax manner: It really depends on your business rules and requirements. No perfect validation process exists because some users may find a way to cheat to some degree, no matter what rules you establish. The trick is to find the right balance of the fewest rules and the proper strictness, without compromising the usability of the application.
The data you collect for validation comes from the Web Forms you provide in your applications. Web Forms are made up of different types of HTML elements that are constructed using raw HTML form elements, ASP.NET HTML server controls, or ASP.NET Web Form server controls. In the end, your forms are made up of many different types of HTML elements, such as textboxes, radio buttons, check boxes, drop-down lists, and more.
As you work through this chapter, you see the different types of validation rules that you can apply to your form elements. Remember that you have no way to validate the truthfulness of the information you collect; instead, you apply rules that respond to such questions as:
Notice from these questions that you can apply more than a single validation rule to an HTML form element (examples of this appear later in this chapter). In fact, you can apply as many rules to a single element as you want. Applying more rules to elements increases the strictness of the validation applied to the data.
If you are new to web application development, you might not be aware of the difference between client-side and server-side validation. Suppose that the end user clicks the Submit button on a form after filling out some information. What happens in ASP.NET is that this form is packaged in a request and sent to the server where the application resides. At this point in the request/response cycle, you can run validation checks on the information submitted. Doing this is called server-side validation because it occurs on the server.
On the other hand, it’s also possible to supply a client-side script (usually in the form of JavaScript) in the page that is posted to the end user’s browser to perform validations on the data entered in the form before the form is posted back to the originating server. In this case, client-side validation has occurred.
Client-side validation is quick and responsive for the end user. It is something end users expect of the forms that they work with. If something is wrong with the form, using client-side validation ensures that the end user knows about it as soon as possible. The reason for this is that the client-side validation, if called properly, executes before the form is posted back to the server. Client-side validation also pushes the processing power required of validation to the client, meaning that you don’t need to spin CPU cycles on the server to process the same information because the client can do the work for you.
With this said, client-side validation is the more insecure form of validation. When a page is generated in an end user’s browser, this end user can look at the code of the page quite easily (simply by right-clicking his mouse in the browser and selecting View Code). When he or she does so, in addition to seeing the HTML code for the page, all of the JavaScript that is associated with the page can be viewed. If you are validating your form client-side, it doesn’t take much for the crafty hacker to repost a form (containing the values he wants in it) to your server as valid. Cases also exist in which clients have simply disabled the client-scripting capabilities in their browsers — thereby making your validations useless. Therefore, client-side validation should be considered a convenience and a courtesy to the end user and never a security mechanism. However, even with the risks, client-side validation is quite popular as it does provide a better user experience.
The more secure form of validation is server-side validation. Server-side validation means that the validation checks are performed on the server instead of on the client. It is more secure because these checks cannot be easily bypassed. Instead, the form data values are checked using server code (C# or VB) on the server. If the form data isn’t valid, the page that is sent back to the client as invalid. Although it is more secure, server-side validation can be slow. It is sluggish simply because the page has to be posted to a remote location and checked. Your end user might not be the happiest surfer in the world if, after waiting 20 seconds for a form to post, he is told his e-mail address isn’t in the correct format.
So what is the correct path? Well, actually, both! The best approach is always to perform client-side validation first and then, after the form passes and is posted to the server, to perform the validation checks again using server-side validation. This approach provides the best of both worlds. It is secure because hackers can’t simply bypass the validation. They may bypass the client-side validation, but they quickly find that their form data is checked once again on the server after it is posted. This validation technique is also highly effective — giving you both the quickness and snappiness of client-side validation.
Getting the forms that are present on your web pages to deal with validation is a common task in web development. For this reason, with the initial release of ASP.NET, the ASP.NET team introduced a series of validation server controls meant to make implementing sound validation for forms a snap.
ASP.NET not only introduces form validations as server controls, but it also makes these controls rather smart. When developing using some other web technologies, developers have to determine where to perform form validation — either on the client or on the server. The ASP.NET validation server controls eliminate this dilemma because ASP.NET performs browser detection when generating the ASP.NET page and makes decisions based on the information it gleans.
This means that if the browser can support the JavaScript that ASP.NET can send its way, the validation occurs on the client-side. If the client cannot support the JavaScript meant for client-side validation, this JavaScript is omitted and the validation occurs on the server.
The best part about this scenario is that even if client-side validation is initiated on a page, ASP.NET still performs the server-side validation when it receives the submitted page, thereby ensuring that security won’t be compromised. This decisive nature of the validation server controls means that you can build your ASP.NET web pages to be the best they can possibly be — rather than dumbing-down your web applications for the lowest common denominator.
Presently, seven validation controls are available to you in ASP.NET 4.5. No new validation server controls have been added to ASP.NET since the initial release of the technology. However, ASP.NET 4.5 did introduce a new validation technique by using unobtrusive JavaScript capabilities, and this is discussed later in this chapter.
The available validation server controls include:
Working with ASP.NET validation server controls is no different from working with any other ASP.NET server control. Each of these controls allows you to drag and drop it onto a design surface or to work with it directly from the code of your ASP.NET page. You can also configure these controls so that they appear exactly as you want — ensuring the visual uniqueness that your applications might require. You see some aspects of both of these items throughout this chapter.
Table 6-1 describes the functionality of each of the available validation server controls.
VALIDATION SERVER CONTROL | DESCRIPTION |
RequiredFieldValidator | Ensures that the user does not skip a form entry field. |
CompareValidator | Allows for comparisons between the user’s input and another item using a comparison operator (equals, greater than, less than, and so on). |
RangeValidator | Checks the user’s input based upon a lower- and upper-level range of numbers or characters. |
RegularExpressionValidator | Checks that the user’s entry matches a pattern defined by a regular expression. This control is good to use to check e-mail addresses and phone numbers. |
CustomValidator | Checks the user’s entry using custom-coded validation logic. |
DynamicValidator | Works with exceptions that are thrown from entity data models and extension methods. This control is part of the ASP.NET Dynamic Data Framework. For more information about this control, be sure to search the Internet for DynamicValidator. |
ValidationSummary | Displays all the error messages from the validators in one specific spot on the page. |
Validation doesn’t just happen; it occurs in response to an event. In most cases, it is a button click event. The Button, LinkButton, and ImageButton server controls all have the capability to cause a page’s form validation to initiate. This is the default behavior. Dragging and dropping a Button server control onto your form gives you the following initial result:
<asp:Button ID="Button1" runat="server" Text="Button" />
If you look through the properties of the Button control, you can see that the CausesValidation property is set to True. As stated, this behavior is the default — all buttons on the page, no matter how many there are, cause the form validation to fire.
If you have multiple buttons on an ASP.NET page, and you don’t want every button to initiate the form validation, you can set the CausesValidation property to False for all the buttons you want to ignore in the validation process (for example, a form’s Cancel button or pressing enter in another form element such as a search box):
<asp:Button ID="Button1" runat="server" Text="Cancel" CausesValidation="false" />
Traditionally, validation is handled on the server-side by using a built-in control or writing a method to check the values on the form. On the client-side, JavaScript would be omitted to the browser. In this scenario, the end user may be overwhelmed with validation messages. In addition, if the JavaScript itself contains errors, the page may not load properly. To circumvent this, the jQuery validation plugin was updated to support unobtrusive validation.
Unobtrusive validation helps to reduce the invasion on the user’s interaction with the web application. Instead of rendering JavaScript inline, HTML5 data-* attributes are added to the appropriate form elements. In ASP.NET 4.5, the jQuery validation plugin is used and the unobtrusive validation functionality is enabled by default.
Unlike previous versions of Visual Studio, Visual Studio 2012 contains an empty project template that is truly empty. This means that a project is added to a solution with only a web.config file. If you choose to create a new website, the web.config file contains only the following:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.5"/>
<httpRuntime targetFramework="4.5"/>
</system.web>
</configuration>
One of the validation controls available to you in ASP.NET is the RequiredFieldValidator. Listing 6-1 shows a simple use of the RequiredFieldValidator control.
LISTING 6-1: A simple use of the RequiredFieldValidator server control
VB
<%@ Page Language="VB" %>
<!DOCTYPE html>
<script runat="server">
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
If Page.IsValid Then
Label1.Text = "Page is valid!"
End If
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1"
runat="server" Text="Required!" ControlToValidate="TextBox1"
EnableClientScript="true">
</asp:RequiredFieldValidator>
<br />
<asp:Button ID="Button1" runat="server" Text="Submit"
OnClick="Button1_Click" />
<br />
<br />
<asp:Label ID="Label1" runat="server"></asp:Label>
</div>
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">
protected void Button1_Click(Object sender, EventArgs e)
{
if (Page.IsValid)
{
Label1.Text = "Page is valid!";
}
}
</script>
If you run this page as is, leaving the textbox blank and submitting the form, you’ll receive an exception, as shown in Figure 6-1.
This exception occurs because ASP.NET is expecting you to define how validation should be rendered. You can enable unobtrusive validation by adding the following to the web.config file:
<appSettings>
<add key="ValidationSettings:UnobtrusiveValidationMode" value="WebForms" />
</appSettings>
The value of ValidationSettings:UnobtrusiveValidationMode can be None or WebForms.
Instead of setting this value in the web.config file, you can also set this value in the global.asax file’s Application_Start method, as shown here:
VB
ValidationSettings.UnobtrusiveValidationMode = UnobtrusiveValidationMode.WebForms
C#
ValidationSettings.UnobtrusiveValidationMode = UnobtrusiveValidationMode.WebForms;
If you want to set this value on a page-by-page basis, you can. In the Page_Load event, add the following:
VB
Page.UnobtrusiveValidationMode = UnobtrusiveValidationMode.WebForms
C#
Page.UnobtrusiveValidationMode = UnobtrusiveValidationMode.WebForms;
If you set the UnobtrusiveValidationMode to use WebForms, you’re not done yet. You still have to register the jQuery JavaScript library with the ASP.NET Ajax ScriptManager (see sidebar).
The RequiredFieldValidator control simply checks to see whether any characters were entered into the HTML form element. It is a simple validation control, but it is one of the most frequently used. You must have a RequiredFieldValidator control for each form element on which you want to enforce a value-required rule.
In the previous section on unobtrusive validation when you tried to use the RequiredFieldValidator control, an exception was thrown. However, since then, you have added jQuery and told ASP.NET to register the scripts with the ScriptManager to resolve this exception. A simple textbox and button appear on the page. Don’t enter any value inside the textbox, but click the Submit button. Figure 6-2 shows the result.
Now look at the code from this example back in Listing 6-1. First, nothing is different about the TextBox, Button, or Label controls. They are constructed just as they would be if you were not using any type of form validation. This page does contain a simple RequiredFieldValidator control, however. Several properties of this control are especially notable because you will use them in most of the validation server controls you create.
The first property to look at is the Text property. This property is the value that is shown to the end user via the web page if the validation fails. In this case, it is a simple Required! string. The second property to look at is the ControlToValidate property. This property is used to make an association between this validation server control and the ASP.NET form element that requires the validation. In this case, the value specifies the only element in the form — the textbox.
As you can see from this example, the error message is constructed from an attribute within the <asp:RequiredFieldValidator> control.
You can also express this error message between the <asp:RequiredFieldValidator> opening and closing nodes, as shown in Listing 6-2.
LISTING 6-2: Placing values between nodes
<asp:RequiredFieldValidator ID="RequiredFieldValidator1"
runat="server" ControlToValidate="TextBox1"
EnableClientScript="true">
Required!
</asp:RequiredFieldValidator>
The RequiredFieldValidator control uses client-side validation if the browser allows it. You can see how the client-side validation works by right-clicking on the page and selecting View Source from the menu. In the page code, you’ll see the markup shown in Listing 6-3.
LISTING 6-3: Partially generated markup
<!-- Abbreviated for clarity -->
<input name="TextBox1" type="text" id="TextBox1" />
<span data-val-controltovalidate="TextBox1" id="RequiredFieldValidator1" data-val="true"
data-val-evaluationfunction="RequiredFieldValidatorEvaluateIsValid"
data-val-initialvalue="" style="visibility:hidden;">
Required!
</span>
<br />
<input type="submit" name="Button1" value="Submit" onclick="javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions("Button1", "", true, "", "", false, false))" id="Button1" />
The WebForm_DoPostBackWithOptions JavaScript function initiates the client-side validation. Notice that the span element includes four attributes that begin with data-val. These attributes help the JavaScript functions determine which elements should be used for validation and how the validation should be handled.
<script type="text/javascript">
//<![CDATA[
var RequiredFieldValidator1 = document.all ? document.all
["RequiredFieldValidator1"] : document.getElementById("RequiredFieldValidator1");
RequiredFieldValidator1.controltovalidate = "TextBox1";
RequiredFieldValidator1.evaluationfunction =
"RequiredFieldValidatorEvaluateIsValid";
RequiredFieldValidator1.initialvalue = "";
//]]>
</script>
One important property of the RequiredFieldValidator control is the InitialValue property. In Listing 6-3, you can see that the initial value is rendered as an attribute named data-val-initialvalue on the span element. Sometimes you have form elements that are populated with some default properties (for example, from a datastore), and these form elements might present the end user with values that require changes before the form can be submitted to the server.
When using the InitialValue property, you specify to the RequiredFieldValidator control the initial text of the element. The end user is then required to change that text value before he or she can submit the form. Listing 6-4 shows an example of using this property.
LISTING 6-4: Working with the InitialValue property
<asp:TextBox ID="TextBox1" runat="server" Text="Wrox"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1"
runat="server" ControlToValidate="TextBox1" InitialValue="Wrox"
EnableClientScript="true" Text="Please change the value of the textbox!" />
In this case, you can see that the InitialValue property contains a value of Wrox. When the page is built and run, the textbox contains this value as well. The RequiredFieldValidator control requires a change in this value for the page to be considered valid.
In the preceding example of the use of the InitialValue property, an interesting problem arises. If you run the associated example, one thing the end user can do to get past the form validation is to submit the page with no value entered in this particular textbox. A blank textbox does not fire a validation error because the RequiredFieldValidator control is now reconstructed to force the end user only to change the default value of the textbox (which he did when he removed the old value). When you reconstruct the RequiredFieldValidator control in this manner, nothing in the validation rule requires that something be entered in the textbox — just that the initial value be changed. The possibility exists for the user to completely bypass the form validation process by just removing anything entered in this textbox.
A way around this problem exists, however, and it goes back to the earlier discussion about how a form is made up of multiple validation rules — some of which are assigned to the same form element. To both require a change to the initial value of the textbox and disallow a blank entry (thereby making the element a required element), you must put an additional RequiredFieldValidator control on the page. This second RequiredFieldValidator control is associated with the same textbox as the first RequiredFieldValidator control. This method is illustrated in the example shown in Listing 6-5.
LISTING 6-5: Using two RequiredFieldValidator controls for one form element
<asp:TextBox ID="TextBox1" runat="server" Text="Wrox"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1"
runat="server" ControlToValidate="TextBox1" InitialValue="Wrox"
EnableClientScript="true" Text="Please change the value of the textbox!" />
<asp:RequiredFieldValidator ID="RequiredFieldValidator2"
runat="server" ControlToValidate="TextBox1"
EnableClientScript="true" Text="Please do not leave this field blank!" />
In this example, you can see that the textbox does indeed have two RequiredFieldValidator controls associated with it. The first, RequiredFieldValidator1, requires a change to the default value of the textbox through the use of the InitialValue property. The second RequiredFieldValidator control, RequiredFieldValidator2, simply makes the TextBox1 control a form element that requires a value. You get the behavior you want by applying two validation rules to a single form element.
So far, you have seen several examples of using the RequiredFieldValidator control with the TextBox control, but you can just as easily use this validation control with other form elements as well.
For example, you can use the RequiredFieldValidator control with an <asp:DropDownList> server control. Suppose that you have a drop-down list that requires the end user to select her profession from a list of items. The first line of the drop-down list includes instructions to the end user about what to select, and you want to make this line a required form element as well. Listing 6-6 shows the code to do so.
LISTING 6-6: Drop-down list validations
<asp:DropDownList ID="DropDownList1" runat="server">
<asp:ListItem Selected="True">Select a profession</asp:ListItem>
<asp:ListItem>Programmer</asp:ListItem>
<asp:ListItem>Lawyer</asp:ListItem>
<asp:ListItem>Doctor</asp:ListItem>
<asp:ListItem>Artist</asp:ListItem>
</asp:DropDownList>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1"
runat="server" Text="Please make a selection"
ControlToValidate="DropDownList1"
InitialValue="Select a profession">
</asp:RequiredFieldValidator>
Just as when you work with the textbox, the RequiredFieldValidator control in this example associates itself with the DropDownList control using the ControlToValidate property. The drop-down list to which the validation control is bound has an initial value — Select a profession. You obviously don’t want your end user to retain that value when she posts the form back to the server. So again, you use the InitialValue property of the RequiredFieldValidator control. The value of this property is assigned to the initial selected value of the drop-down list. This value forces the end user to select one of the provided professions in the drop-down list before she can post the form.
The CompareValidator control enables you to compare two form elements as well as to compare values contained within form elements to a constant value that you specify. For example, you can specify that a form element’s value must be an integer and greater than a specified number. You can also state that values must be strings, dates, or other data types that are at your disposal for comparison purposes.
One of the more common ways of using the CompareValidator control is to make a comparison between two form elements. For example, suppose that you have an application that requires users to have passwords in order to access the site. You create one textbox asking for the user’s password and a second textbox that asks the user to confirm the password. Because the textbox is in password mode, the end user cannot see what she is typing — just the number of characters that she has typed. To reduce the chances of the end user mistyping her password and inputting this incorrect password into the system, you ask her to confirm the password. After the form is input into the system, you simply have to make a comparison between the two textboxes to see whether they match. If they match, it is likely that the end user typed the password correctly, and you can input the password choice into the system. If the two textboxes do not match, you want the form to be invalid. Listing 6-7 demonstrates this situation.
LISTING 6-7: Using the CompareValidator to test values against other control values
VB
<%@ Page Language="VB" %>
<!DOCTYPE html>
<script runat="server">
Protected Sub Button1_Click(sender As Object, e As EventArgs)
If Page.IsValid Then
Label1.Text = "Passwords match"
End If
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>CompareFieldValidator</title>
</head>
<body>
<form id="form1" runat="server">
<p>
Password<br />
<asp:TextBox ID="TextBox1" runat="server"
TextMode="Password"></asp:TextBox>
<asp:CompareValidator ID="CompareValidator1"
runat="server" Text="Passwords do not match!"
ControlToValidate="TextBox2"
ControlToCompare="TextBox1"></asp:CompareValidator>
</p>
<p>
Confirm Password<br />
<asp:TextBox ID="TextBox2" runat="server"
TextMode="Password"></asp:TextBox>
</p>
<p>
<asp:Button ID="Button1" OnClick="Button1_Click"
runat="server" Text="Login"></asp:Button>
</p>
<p>
<asp:Label ID="Label1" runat="server"></asp:Label>
</p>
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">
protected void Button1_Click(Object sender, EventArgs e) {
if (Page.IsValid)
Label1.Text = "Passwords match";
}
</script>
Looking at the CompareValidator control on the form, you can see that it is similar to the RequiredFieldValidator control. The CompareValidator control has a property called ControlToValidate that associates itself with one of the form elements on the page. In this case, you need only a single CompareValidator control on the page because a single comparison is made. In this example, you are making a comparison between the value of TextBox2 and that of TextBox1. Therefore, you use the ControlToCompare property. This specifies what value is compared to TextBox2. In this case, the value is TextBox1.
It’s as simple as that. If the two textboxes do not match after the end user posts the page, the value of the Text property from the CompareValidator control appears in the browser. Figure 6-3 shows an example of this situation.
Besides being able to validate values against values in other controls, you can also use the CompareValidator control to make comparisons against constants of specific data types. For example, suppose you have a textbox on your registration form that asks for the age of the user. In most cases, you want to get back an actual number and not something such as aa or bb as a value. Listing 6-8 shows you how to ensure that you get back an actual number.
LISTING 6-8: Using the CompareValidator to validate against constants
Age:
<asp:TextBox ID="TextBox1" runat="server" MaxLength="3">
</asp:TextBox>
<asp:CompareValidator ID="CompareValidator1" runat="server"
Text="You must enter a number"
ControlToValidate="TextBox1" Type="Integer"
Operator="DataTypeCheck"></asp:CompareValidator>
In this example, the end user is required to type a number into the textbox. If he attempts to bypass the validation by entering a fake value that contains anything other than a number, the page is identified as invalid, and the CompareValidator control displays the value of the Text property.
To specify the data types that you want to use in these comparisons, you simply use the Type property. The Type property can take the following values:
Not only can you make sure that what is entered is of a specific data type, but you can also make sure that what is entered is valid when compared to specific constants. For example, you can make sure what is entered in a form element is greater than, less than, equal to, greater than or equal to, or less than or equal to a specified value. Listing 6-9 shows an example of this situation.
LISTING 6-9: Making comparisons with the CompareValidator control
Age:
<asp:TextBox ID="TextBox1" runat="server" MaxLength="3">
</asp:TextBox>
<asp:CompareValidator ID="CompareValidator1" runat="server"
Text="You must be at least 18 to join"
ControlToValidate="TextBox1" Type="Integer"
Operator="GreaterThanEqual" ValueToCompare="18"></asp:CompareValidator>
In this case, the CompareValidator control not only associates itself with the TextBox1 control and requires that the value must be an integer, but it also uses the Operator and the ValueToCompare properties to ensure that the number is greater than 18. Therefore, if the end user enters a value of 18 or less, the validation fails, and the page is considered invalid.
The Operator property can take one of the following values:
The ValueToCompare property is where you place the constant value used in the comparison. In the preceding example, it is the number 18.
The RangeValidator control is quite similar to that of the CompareValidator control, but it makes sure that the end-user value or selection provided is within a specified range as opposed to being just greater than or less than a specified constant. For an example of this control, think back to the textbox element that asks for the age of the end user and performs a validation on the value provided. Listing 6-10 demonstrates this validation.
LISTING 6-10: Using the RangeValidator control to test an integer value
Age:
<asp:TextBox ID="TextBox1" runat="server" MaxLength="3">
</asp:TextBox>
<asp:RangeValidator ID="RangeValidator1" runat="server"
ControlToValidate="TextBox1" Type="Integer"
Text="You must be between 30 and 40"
MaximumValue="40" MinimumValue="30"></asp:RangeValidator>
In this example, this page consists of a textbox asking for the age of the end user. The RangeValidator control makes an analysis of the value provided and makes sure the value is somewhere in the range, including the minimum and maximum values, of 30 to 40. You set the range using the MaximumValue and MinimumValue properties. The RangeValidator control also makes sure that what is entered is an integer data type. It uses the Type property, which is set to Integer. The other possible data types for the RangeValidator control include the same values used, and as mentioned earlier, for the CompareValidator control. The collection of screenshots in Figure 6-4 shows this example in action.
As you can see from the screenshots in Figure 6-4, a value of less than 30 causes the RangeValidator control to fire, as does a number greater than 40. A value that is somewhere between 30 and 40 (in this case 36) conforms to the validation rule of the control.
The RangeValidator control is not only about validating numbers (although it is most often used in this fashion). It can also be about validating a range of string characters as well as other items, including calendar dates. By default, the Type property of any of the validation controls is set to String, which allows you to ensure that the string’s ASCII value submitted is within a particular range. You can use the RangeValidator control to make sure that what is entered in another server control (such as a Calendar control) is within a certain range of dates.
For example, suppose that you are building a Web Form that asks for a customer’s arrival date, and the arrival date needs to be within two weeks of the current date. You can use the RangeValidator control to test for these scenarios quite easily.
Because the date range that you want to check is dynamically generated, you assign the MaximumValue and MinimumValue properties programmatically in the Page_Load event. In the Designer, your sample page for this example should look like Figure 6-5.
The idea is that the end user will select a date from the Calendar control, which will then populate the TextBox control. Then, when the end user clicks the form’s button, he is notified if the date selected is invalid. If the date selected is valid, that date is presented through the Label control on the page. Listing 6-11 presents the code for this example.
LISTING 6-11: Using the RangeValidator control to test a string date value
VB
<%@ Page Language="VB" %>
<!DOCTYPE html>
<script runat="server">
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
RangeValidator1.MinimumValue = DateTime.Now.ToShortDateString()
RangeValidator1.MaximumValue = DateTime.Now.AddDays(14).ToShortDateString()
End Sub
Protected Sub Calendar1_SelectionChanged(ByVal sender As Object, _
ByVal e As System.EventArgs)
TextBox1.Text = Calendar1.SelectedDate.ToShortDateString()
End Sub
Protected Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs)
If Page.IsValid Then
Label1.Text = "You are set to arrive on: " & TextBox1.Text
End If
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Date Validation Check</title>
</head>
<body>
<form id="form1" runat="server">
Arrival Date:
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:RangeValidator ID="RangeValidator1" runat="server"
Text="You must only select a date within the next two weeks."
ControlToValidate="TextBox1" Type="Date"></asp:RangeValidator>
<br />
<br />
Select your arrival date:<br />
<asp:Calendar ID="Calendar1" runat="server"
OnSelectionChanged="Calendar1_SelectionChanged"></asp:Calendar>
<br />
<asp:Button ID="Button1" runat="server" Text="Button"
OnClick="Button1_Click" />
<br />
<br />
<asp:Label ID="Label1" runat="server"></asp:Label>
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
RangeValidator1.MinimumValue = DateTime.Now.ToShortDateString();
RangeValidator1.MaximumValue =
DateTime.Now.AddDays(14).ToShortDateString();
}
protected void Calendar1_SelectionChanged(object sender, EventArgs e)
{
TextBox1.Text = Calendar1.SelectedDate.ToShortDateString();
}
protected void Button1_Click(object sender, EventArgs e)
{
if (Page.IsValid)
{
Label1.Text = "You are set to arrive on: " + TextBox1.Text.ToString();
}
}
</script>
From this code, you can see that when the page is loaded, the MinimumValue and MaximumValue attributes are assigned a dynamic value. In this case, the MinimumValue gets the DateTime.Now.ToShortDateString() value, whereas the MaximumValue gets a date of 14 days later.
After the end user selects a date, the selected date is populated in the TextBox1 control using the Calendar1_SelectionChanged event. After the user selects a date and clicks the button on the page, the Button1_Click event is fired and the page is checked for form validity using the Page.IsValid property. By using the Page.IsValid property, each of the validation controls are checked to ensure that validation passes. If it does, the value returned is true. Otherwise, a false value is returned. An invalid page gives you the result shown in Figure 6-6.
One exciting control that developers like to use is the RegularExpressionValidator control. This control offers a lot of flexibility when you apply validation rules to your Web Forms. Using the RegularExpressionValidator control, you can check a user’s input based on a pattern that you define using a regular expression.
This means that you can define a structure that a user’s input will be applied against to see whether its structure matches the one that you define. For example, you can define that the structure of the user input must be in the form of an e-mail address or an Internet URL; if it doesn’t match this definition, the page is considered invalid. Listing 6-12 shows you how to validate what is typed into a textbox by making sure it is in the form of an e-mail address.
LISTING 6-12: Making sure the textbox value is an e-mail address
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:RegularExpressionValidator ID="RegularExpressionValidator1" runat="server"
Text="You must enter an email address"
ValidationExpression="\w+([-+.']\w+)*@\w+([-.]\w+)*.\w+([-.]\w+)*"
ControlToValidate="TextBox1"></asp:RegularExpressionValidator>
Just like the other validation server controls, the RegularExpressionValidator control uses the ControlToValidate property to bind itself to the TextBox control, and it includes a Text property to push out the error message to the screen if the validation test fails. The unique property of this validation control is the ValidationExpression property. This property takes a string value, which is the regular expression you are going to apply to the input value.
Visual Studio makes using regular expressions a little easier through the use of the Regular Expression Editor. This editor provides a few commonly used regular expressions that you might want to apply to your RegularExpressionValidator. To get at this editor, you work with your page from the Design view. Be sure to highlight the RegularExpressionValidator1 server control in this Design view to see the control’s properties. In the Property window of Visual Studio, click the button found next to the ValidationExpression property to launch the Regular Expression Editor. Figure 6-7 shows this editor.
Using this editor, you can find regular expressions for things like e-mail addresses, Internet URLs, ZIP codes, phone numbers, and social security numbers.
So far, you have seen a wide variety of validation controls that are at your disposal. In many cases, these validation controls address many of the validation rules that you want to apply to your Web Forms. Sometimes, however, none of these controls works for you, and you have to go beyond what they offer. This is where the CustomValidator control comes into play.
The CustomValidator control enables you to build your own client-side or server-side validations that you can then easily apply to your Web Forms. Doing so enables you to make validation checks against values or calculations performed in the data tier (for example, in a database), or to make sure that the user’s input validates against some arithmetic validation (for example, determining whether a number is even or odd). You can do quite a bit with the CustomValidator control.
One of the worthwhile functions of the CustomValidator control is its capability to easily provide custom client-side validations. Many developers have their own collections of JavaScript functions that they employ in their applications, and using the CustomValidator control is one easy way of getting these functions implemented with minimal changes to the functions. As an example, in most cases, the JavaScript function signature must be updated to adhere to a specific signature.
For example, look at a simple form that asks for a number from the end user. This form uses the CustomValidator control to perform a custom client-side validation on the user input to make sure that the number provided is divisible by 5. Listing 6-13 shows the code for this validation.
LISTING 6-13: Using the CustomValidator control to perform client-side validations
VB
<%@ Page Language="VB" %>
<!DOCTYPE html>
<script runat="server">
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Label1.Text = "VALID NUMBER!"
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>CustomValidator</title>
<script type="text/javascript">
function validateNumber(oSrc, args) {
args.IsValid = (args.Value % 5 == 0);
}
</script>
</head>
<body>
<form id="form1" runat="server">
<p>
Number:
<asp:TextBox ID="TextBox1"
runat="server"></asp:TextBox>
<asp:CustomValidator ID="CustomValidator1"
runat="server" ControlToValidate="TextBox1"
Text="Number must be divisible by 5"
ClientValidationFunction="validateNumber">
</asp:CustomValidator>
</p>
<p>
<asp:Button ID="Button1" OnClick="Button1_Click"
runat="server" Text="Button"></asp:Button>
</p>
<p>
<asp:Label ID="Label1" runat="server"></asp:Label>
</p>
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">
protected void Button1_Click(Object sender, EventArgs e)
{
Label1.Text = "VALID NUMBER!";
}
</script>
Looking over this Web Form, you can see a couple of things happening. It is a simple form with only a single textbox requiring user input. The user clicks the button that triggers the Button1_Click event, which in turn populates the Label1 control on the page. It carries out this simple operation only if all the validation checks are performed and the user input passes these tests.
One item that is different about this page is the inclusion of the second <script> block found within the <head> section. This is the custom JavaScript. Note that Visual Studio 2012 is very friendly toward these kinds of constructions, even when you are switching between the Design and Code views of the page — something Visual Studio editions prior to 2008 were rather poor at dealing with. This JavaScript function — validateNumber — is shown here:
<script type="text/javascript">
function validateNumber(oSrc, args) {
args.IsValid = (args.Value % 5 == 0);
}
</script>
This second <script> section is the client-side JavaScript that you want the CustomValidator control to use when making its validation checks on the information entered into the textbox. Similarly to the server-side validation methods, the client-side validation method will require two parameters: the source parameter and the arguments parameter. The source parameter is a reference to the validation control itself. The arguments parameter is an object containing two properties, args.IsValid and args.Value. The JavaScript functions you employ are going to use the args.IsValid property and set this property to True or False, depending on the outcome of the validation check. In this case, the user input (args.Value) is checked to see whether it is divisible by 5. The Boolean value returned is then assigned to the args.IsValid property, which is then used by the CustomValidator control.
The CustomValidator control, like the other controls before it, uses the ControlToValidate property to associate itself with a particular element on the page. The property that you are interested in here is the ClientValidationFunction property. The string value provided to this property is the name of the client-side function that you want this validation check to employ when the CustomValidator control is triggered. In this case, it is validateNumber:
ClientValidationFunction="validateNumber"
If you run this page and make an invalid entry, you produce the result shown in Figure 6-8.
Now let’s move this same validation check from the client to the server. The CustomValidator control enables you to make custom server-side validations a reality as well. You will find that creating your server-side validations is just as easy as creating client-side validations.
If you create your own server-side validations, you can make them as complex as your applications require. For example, using the CustomValidator for server-side validations is something you do if you want to check the user’s input against dynamic values coming from XML files, databases, or elsewhere.
For an example of using the CustomValidator control for some custom server-side validation, you can work with the same example as you did when creating the client-side validation. Now, create a server-side check that makes sure a user input number is divisible by 5, as shown in Listing 6-14.
LISTING 6-14: Using the CustomValidator control to perform server-side validations
VB
<%@ Page Language="VB" %>
<!DOCTYPE html>
<script runat="server">
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
If Page.IsValid Then
Label1.Text = "VALID ENTRY!"
End If
End Sub
Sub ValidateNumber(sender As Object, args As ServerValidateEventArgs)
Try
Dim num As Integer = Integer.Parse(args.Value)
args.IsValid = ((num Mod 5) = 0)
Catch ex As Exception
args.IsValid = False
End Try
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>CustomValidator</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<p>
Number:
<asp:TextBox ID="TextBox1"
runat="server"></asp:TextBox>
<asp:CustomValidator ID="CustomValidator1"
runat="server" ControlToValidate="TextBox1"
Text="Number must be divisible by 5"
OnServerValidate="ValidateNumber"></asp:CustomValidator>
</p>
<p>
<asp:Button ID="Button1" OnClick="Button1_Click"
runat="server" Text="Button"></asp:Button>
</p>
<p>
<asp:Label ID="Label1" runat="server"></asp:Label>
</p>
</div>
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">
protected void Button1_Click(Object sender, EventArgs e)
{
if (Page.IsValid)
{
Label1.Text = "VALID ENTRY!";
}
}
void ValidateNumber(object source, ServerValidateEventArgs args)
{
try
{
int num = int.Parse(args.Value);
args.IsValid = ((num % 5) == 0);
}
catch (Exception ex)
{
args.IsValid = false;
}
}
</script>
Instead of a client-side JavaScript function in the code, this example includes a server-side function — ValidateNumber. The server-side function accepts the same two parameters that the client-side function uses. The ValidateNumber function, as well as all functions that are being constructed to work with the CustomValidator control, must use the ServerValidateEventArgs object as one of the parameters in order to get the data passed to the function for the validation check. The ValidateNumber function itself is nothing fancy. It simply checks to see whether the provided number is divisible by 5.
From within your custom function, which is designed to work with the CustomValidator control, you actually get at the value coming from the form element through the args.Value object. Then you set the args.IsValid property to True or False, depending on your validation checks. From the preceding example, you can see that the args.IsValid is set to False if the number is not divisible by 5 and also that an exception is thrown (which would occur if a string value were input into the form element). After the custom function is established, the next step is to apply it to the CustomValidator control, as shown in the following example:
<asp:CustomValidator ID="CustomValidator1"
runat="server" ControlToValidate="TextBox1"
Text="Number must be divisible by 5"
OnServerValidate="ValidateNumber"></asp:CustomValidator>
To make the association between a CustomValidator control and a function that you have in your server-side code, you simply use the OnServerValidate server-side event. The value assigned to this property is the name of the function — in this case, ValidateNumber.
Running this example causes the postback to come back to the server and the validation check (based on the ValidateNumber function) to be performed. From here, the page reloads and the Page_Load event is called. In the example from Listing 6-14, you can see that a check is done to determine whether the page is valid. This check uses the Page.IsValid property:
if (Page.IsValid)
{
Label1.Text = "VALID ENTRY!";
}
As stated earlier in this chapter, you have to think about the security of your forms and to ensure that the data you are collecting from the forms is valid. For this reason, when you decide to employ client-side validations (as you did in Listing 6-13), you should take steps to also reconstruct the client-side function as a server-side function. When you have done this task, you should associate the CustomValidator control to both the client-side and server-side functions. In the case of the number check validation from Listings 6-13 and 6-14, you can use both validation functions in your page and then change the CustomValidator control to point to both of these functions, as shown in Listing 6-15.
LISTING 6-15: The CustomValidator control with client- and server-side validations
<asp:CustomValidator ID="CustomValidator1"
runat="server" ControlToValidate="TextBox1"
Text="Number must be divisible by 5"
OnServerValidate="ValidateNumber"
ClientValidationFunction="validateNumber"></asp:CustomValidator>
From this example, you can see it is simply a matter of using the ClientValidationFunction and OnServerValidate attributes at the same time.
The ValidationSummary control does not perform validations on the content input into your Web Forms. Instead, it’s a reporting control that the other validation controls on a page use. You can use this validation control to consolidate error reporting for all the validation errors that occur on a page instead of leaving it up to each individual validation control.
You might want this capability for larger forms, which have a comprehensive form-validation process. In this case, you may find having all the possible validation errors reported to the end user in a single and easily identifiable manner to be rather user-friendly. You can display these error messages in a list, bulleted list, or paragraph.
By default, the ValidationSummary control shows the list of validation errors as a bulleted list, as shown in Listing 6-16.
LISTING 6-16: A partial page example of the ValidationSummary control
<p>
First name
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1"
runat="server" ErrorMessage="You must enter your first name"
ControlToValidate="TextBox1"></asp:RequiredFieldValidator>
</p>
<p>
Last name
<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator2"
runat="server" ErrorMessage="You must enter your last name"
ControlToValidate="TextBox2"></asp:RequiredFieldValidator>
</p>
<p>
<asp:Button ID="Button1" OnClick="Button1_Click" runat="server"
Text="Submit"></asp:Button>
</p>
<p>
<asp:ValidationSummary ID="ValidationSummary1" runat="server"
HeaderText="You received the following errors:"></asp:ValidationSummary>
</p>
<p>
<asp:Label ID="Label1" runat="server"></asp:Label>
</p>
This example asks the end user for her first and last name. Each textbox in the form has an associated RequiredFieldValidator control assigned to it. When the page is built and run, the user’s clicking the Submit button with no values placed in either of the textboxes causes both validation errors to fire. Figure 6-9 shows this result.
As in earlier examples of validation controls on the form, these validation errors appear next to each of the textboxes. You can see, however, that the ValidationSummary control also displays the validation errors as a bulleted list at the location of the control on the Web Form. In most cases, you do not want these errors to appear twice on a page for the end user. You can change this behavior by using the Text property of the validation controls, in addition to the ErrorMessage property, as you have typically done throughout this chapter. The Text property is the value of the text displayed within the validation control. The ErrorMessage property is the value of the text displayed within the validation summary (if added to the page). Listing 6-17 shows this approach.
LISTING 6-17: Using the Text property of a validation control
<asp:RequiredFieldValidator ID="RequiredFieldValidator1"
runat="server" ErrorMessage="You must enter your first name"
Text="*" ControlToValidate="TextBox1"></asp:RequiredFieldValidator>
Making this type of change to the validation controls produces the results shown in Figure 6-10.
To get this result, just remember that the ValidationSummary control uses the validation control’s ErrorMessage property for displaying the validation errors if they occur. The Text property is used by the validation control and is not utilized by the ValidationSummary control.
In addition to bulleted lists, you can use the DisplayMode property of the ValidationSummary control to change the display of the results to other types of formats. This control has the following possible values:
You can also utilize a dialog box instead of displaying the results to the web page. The dialog box uses a JavaScript message box to display the results. Listing 6-18 shows an example of this behavior.
LISTING 6-18: Using a dialog box to report validation errors
<asp:ValidationSummary ID="ValidationSummary1" runat="server"
ShowMessageBox="true" ShowSummary="false"></asp:ValidationSummary>
From this code example, you can see that the ShowSummary property is set to false — meaning that the bulleted list of validation errors are not shown on the actual web page. However, because the ShowMessageBox property is set to true, you now get these errors reported in a message box, as shown in Figure 6-11.
Because validation server controls provide clients with client-side validations automatically (if the requesting container can properly handle the JavaScript produced), you might, at times, want a way to control this behavior.
Turning off the client-side capabilities of these controls so that they don’t independently send client-side capabilities to the requestors is quite possible. For example, you might want all validations done on the server, no matter what capabilities the requesting containers offer. You can take a few approaches to turning off this functionality.
The first option is at the control level. Each of the validation server controls has a property called EnableClientScript. This property is set to True by default, but setting it to False prevents the control from sending out a JavaScript function for validation on the client. Instead, the validation check is done on the server. Listing 6-19 shows the use of this property.
LISTING 6-19: Disabling client-side validations in a validation control
<asp:RequiredFieldValidator ID="RequiredFieldValidator1"
runat="server" ErrorMessage="You must enter your first name"
Text="*" ControlToValidate="TextBox1" EnableClientScript="false">
</asp:RequiredFieldValidator>
You can also remove a validation control’s client-side capability programmatically (shown in Listing 6-20).
LISTING 6-20: Removing the client-side capabilities programmatically
VB
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
RequiredFieldValidator1.EnableClientScript = False
RequiredFieldValidator2.EnableClientScript = False
End Sub
C#
protected void Page_Load(Object sender, EventArgs e)
{
RequiredFieldValidator1.EnableClientScript = false;
RequiredFieldValidator2.EnableClientScript = false;
}
Another option is to turn off the client-side script capabilities for all the validation controls on a page from within the Page_Load event. This method can be rather helpful if you want to dynamically decide not to allow client-side validation. Listing 6-21 shows this option.
LISTING 6-21: Disabling all client-side validations from the Page_Load event
VB
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
For Each bv As BaseValidator In Page.Validators
bv.EnableClientScript = False
Next
End Sub
C#
protected void Page_Load(Object sender, EventArgs e)
{
foreach (BaseValidator bv in Page.Validators)
{
bv.EnableClientScript = false;
}
}
By looking for each instance of a BaseValidator object in the validators contained on an ASP.NET page, this For Each loop turns off client-side validation capabilities for each validation control the page contains.
So far, you have been displaying simple textual messages for the error notifications that come from the validation server controls. In most instances, you are going to do just that — display some simple textual messages to inform end users that they typed something into the form that doesn’t pass your validation rules.
An interesting tip regarding the validation controls is that you are not limited to just text — you can also use images and sounds for error notifications.
To use an image for the error, you use the Text property of any of the validation controls. You simply place some appropriate HTML as the value of this property, as shown in Listing 6-22.
LISTING 6-22: Using images for error notifications
<asp:RequiredFieldValidator ID="RequiredFieldValidator1"
runat="server" Text="<img src='error.jpg' alt='Error!' />"
ControlToValidate="TextBox1" EnableClientScript="true">
</asp:RequiredFieldValidator>
As you can see from this example, instead of some text being output to the web page, the value of the Text property is an HTML string. This bit of HTML is used to display an image. Be sure to notice the use of the single and double quotation marks so you won’t get any errors when the browser generates the page. This example produces something similar to Figure 6-12.
The other interesting twist you can create is to add a sound notification when an error occurs. You can do so the same way you display an image for error notifications. Listing 6-23 shows an example of this.
LISTING 6-23: Using sound for error notifications
<asp:RequiredFieldValidator ID="RequiredFieldValidator1"
runat="server" ControlToValidate="TextBox1" EnableClientScript="false"
Text="<audio controls='' src='C:\Windows\Media\tada.wav' autoplay='autoplay'></audio>">
</asp:RequiredFieldValidator>
You can find a lot of the Windows system sounds in the C:\Windows\Media directory. In this example, the Text uses the <audio> element to place a sound on the Web Form (works only with HTML5-compliant browsers). The sound plays only when the end user triggers the validation control.
When working with sounds for error notifications, you have to disable the client-side script capability for that particular control because if you do not, the sound plays when the page loads in the browser, whether or not a validation error has been triggered.
In many instances, developers want to place more than one form on a single page. Different validation controls are often assigned to two distinct forms on the page. However, in this example, unexpected behavior may occur. For instance, when the end user submits one form, the validation controls in the other form may be fired even though the user is not working with that form. This will cause the first form from being submitted. In other scenarios, developers may want to simply break up a form and validate controls differently.
Figure 6-13, for example, shows a basic page for the .NET Valley User Group that includes two forms.
One of the forms is for members of the site to supply their usernames and passwords to log into the Members Only section of the site. The second form on the page is for anyone who wants to sign up for the user group’s newsletter. Each form has its own button and some validation controls associated with it. The problem arises when someone submits information for one of the forms. For example, if you are a member of the group, you supply your username and password, and click the Login button. The validation controls for the newsletter form would fire because no e-mail address was placed in that particular form. If someone interested in getting the newsletter places an e-mail address in the last textbox and clicks the Sign-up button, the validation controls in the first form fire because no username and password were input in that form.
ASP.NET Web Controls contains a ValidationGroup property that enables you to separate the validation controls into separate groups. It enables you to activate only the required validation controls when an end user clicks a button on the page. Listing 6-24 shows an example of separating the validation controls on a user group page into different buckets.
LISTING 6-24: Using the ValidationGroup property
<%@ Page Language="C#" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Validation Groups</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h1>.NET Valley User Group</h1>
Username:
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox> Password:
<asp:TextBox ID="TextBox2" runat="server"
TextMode="Password"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Login"
ValidationGroup="Login" />
<br />
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server"
Text="* You must submit a username!"
ControlToValidate="TextBox1" ValidationGroup="Login">
</asp:RequiredFieldValidator>
<br />
<asp:RequiredFieldValidator ID="RequiredFieldValidator2" runat="server"
Text="* You must submit a password!"
ControlToValidate="TextBox2" ValidationGroup="Login">
</asp:RequiredFieldValidator>
<p>
.NET Valley usually meets the third Thursday of each month alternating meeting
locations between the Luzerne County Community College and Penn State
Wilkes-Barre in Pennsylvania.
The .NET Valley User Group is unique in that meetings focus on technology in
general rather than just .NET technologies. Be sure to check the website for
more details.<br />
</p>
<h2>Sign-up for the newsletter!</h2>
Email:
<asp:TextBox ID="TextBox3" runat="server"></asp:TextBox>
<asp:Button ID="Button2" runat="server" Text="Sign-up"
ValidationGroup="Newsletter" />
<br />
<asp:RegularExpressionValidator ID="RegularExpressionValidator1"
runat="server"
Text="* You must submit a correctly formatted email address!"
ControlToValidate="TextBox3" ValidationGroup="Newsletter"
ValidationExpression="\w+([-+.]\w+)*@\w+([-.]\w+)*.\w+([-.]\w+)*">
</asp:RegularExpressionValidator>
<br />
<asp:RequiredFieldValidator ID="RequiredFieldValidator3" runat="server"
Text="* You forgot your email address!"
ControlToValidate="TextBox3" ValidationGroup="Newsletter">
</asp:RequiredFieldValidator>
</div>
</form>
</body>
</html>
You can see that the ValidationGroup property takes a String value. The core server controls also have the ValidationGroup property because things like button clicks must be associated with specific validation groups.
In this example, each of the buttons has a distinct validation group assignment. The first button on the form uses Login as a value, and the second button on the form uses Newsletter as a value. Then each of the validation controls is associated with one of these validation groups. Because of these associations, when the end user clicks the Login button on the page, ASP.NET recognizes that it should work only with the validation server controls that have the same validation group name. ASP.NET ignores the validation controls assigned to other validation groups.
Using this enhancement, you can now have multiple sets of validation rules that fire only when you want them to fire (see Figure 6-14).
Another great feature with the validation controls is a property called SetFocusOnError. This property takes a Boolean value and, if a validation error is thrown when the form is submitted, the property places the page focus on the form element that receives the error. The SetFocusOnError property is used in the following example:
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server"
Text="* You must submit a username!" SetFocusOnError="true"
ControlToValidate="TextBox1" ValidationGroup="Login">
</asp:RequiredFieldValidator>
If RequiredFieldValidator1 throws an error because the end user didn’t place a value in TextBox1, the page is redrawn with the focus on TextBox1, as shown in Figure 6-15.
Note that if you have multiple validation controls on your page with the SetFocusOnError property set to True, and more than one validation error occurs, the uppermost form element that has a validation error gets the focus. In the previous example, if both the username textbox (TextBox1) and the password textbox (TextBox2) have validation errors associated with them, the page focus is assigned to the username textbox because it is the first control on the form with an error.
Validation controls are a powerful tool at your disposal when you are working with forms. They bring a lot of functionality in a simple-to-use package and, like most things in the .NET world, you can easily get them to look and behave exactly as you want them to.
Remember that the purpose of having forms in your applications is to collect data, but this data collection has no meaning if the data is not valid. This means that you must establish validation rules that can be implemented in your forms through a series of different controls — the validation server controls.
This chapter covered various validation controls in detail, including:
In addition to looking at the basic validation controls, this chapter also discussed how to apply client-side and server-side validations. You also had a chance to see how ASP.NET 4.5 introduced unobtrusive validation and the impact that has with your client-side validation.