Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Pro ASP.NET 2.0 In CSharp 2005 (2005) [eng]

.pdf
Скачиваний:
92
Добавлен:
16.08.2013
Размер:
29.8 Mб
Скачать

138 C H A P T E R 4 S E R V E R C O N T R O L S

The Operator property allows you to specify the type of comparison you want to do. The available values are Equal, NotEqual, GreaterThan, GreaterThanEqual, LessThan, LessThanEqual, and DataTypeCheck. The DataTypeCheck value forces the validation control to check that the input has the required data type (specified through the Type property), without performing any additional comparison.

The following example compares an input with a constant value in order to ensure that the specified age is greater than or equal to 18:

<asp:TextBox runat="server" ID="Age" /> <asp:CompareValidator runat="server" Display="dynamic"

ControlToValidate="Age" ValueToCompare="18" ErrorMessage="You must be at least 18 years old" Type="Integer" Operator="GreaterThanEqual">*

</asp:CompareValidator>

The next example compares the input values in two password text boxes to ensure that their value is the same:

<asp:TextBox runat="server" TextMode="Password" ID="Password" /> <asp:TextBox runat="server" TextMode="Password" ID="Password2" /> <asp:CompareValidator runat="server"

ControlToValidate="Password2" ControlToCompare="Password" ErrorMessage="The passwords don't match"

Type="String" Display="dynamic">

<img src="imgError.gif" border="0" alt="The passwords don't match"> </asp:CompareValidator>

This example also demonstrates another useful technique. The previous examples have used an asterisk (*) to indicate errors. However, this control tag uses an <img> tag to show a small image file of an exclamation mark instead.

The RegularExpressionValidator Control

The RegularExpressionValidator control is a powerful tool in the ASP.NET developer’s toolbox. It allows you to validate text by matching against a pattern defined in a regular expression. You simply need to set the regular expression in the ValidationExpression property.

Regular expressions are also powerful tools—they allow you to specify complex rules that specify the characters, and in what sequence (position and number of occurrences) they are allowed,

in the string. For example, the following control checks that the text input in the text box is a valid e-mail address:

<asp:TextBox runat="server" ID="Email" /> <asp:RegularExpressionValidator runat="server"

ControlToValidate="Email" ValidationExpression=".*@.{2,}\..{2,}" ErrorMessage="E-mail is not in a valid format" Display="dynamic">*

</asp:RegularExpressionValidator>

The expression .*@.{2,}\..{2,} specifies that the string that it’s validating must begin with a number of characters (.*) and must contain an @ character, at least two more characters (the domain name), a period (escaped as \.), and, finally, at least two more characters for the domain extension. For example, marco@apress.com is a valid e-mail address, while marco@apress or marco.apress.com would fail validation. The proposed expression is quite simple in reality. Using a more complex regular expression, you could check that the domain name is valid, that the extension is not made up (see http://www.icann.org for a list of allowed domain name extensions), and so on. However, regular expressions obviously don’t provide any way to check that a domain actually exists or is online.

C H A P T E R 4 S E R V E R C O N T R O L S

139

Table 4-17 summarizes the commonly used syntax constructs (modifiers) for regular expressions.

Table 4-17. Metacharacters for Matching Single Characters

Character Escapes

Description

Ordinary characters

Characters other than .$^{[(|)*+?\ match themselves.

\b

Matches a backspace.

\t

Matches a tab.

\r

Matches a carriage return.

\v

Matches a vertical tab.

\f

Matches a form feed.

\n

Matches a newline.

\

If followed by a special character (one of .$^{[(|)*+?\), this character

 

escape matches that character literal. For example, \+ matches the +

 

character.

 

 

In addition to single characters, you can specify a class or a range of characters that can be matched in the expression. For example, you could allow any digit or any vowel in any position and exclude all the other characters. The metacharacters in Table 4-18 accomplish this.

Table 4-18. Metacharacters for Matching Types of Characters

Character Class

Description

.

Matches any character except \n.

[aeiou]

Matches any single character specified in the set.

[^aeiou]

Matches any character not specified in the set.

[3-7a-dA-D]

Matches any character specified in the specified ranges (in the example

 

the ranges are 3–7, a–d, A–D).

\w

Matches any word character; that is, any alphanumeric character or the

 

underscore (_).

\W

Matches any nonword character.

\s

Matches any whitespace character (space, tab, form-feed, newline,

 

carriage return, or vertical feed).

\S

Matches any nonwhitespace character.

\d

Matches any decimal character.

\D

Matches any nondecimal character.

 

 

Using more advanced syntax, you can specify that a certain character or class of characters must be present at least once, or between two and six times, and so on. The quantifiers are placed just after a character or a range of characters and allow you to specify how many times the preceding character must be matched (see Table 4-19).

140 C H A P T E R 4 S E R V E R C O N T R O L S

Table 4-19. Quantifiers

Quantifier Description

*

Zero or more matches

+One or more matches

?

Zero or one matches

{N}

N matches

{N,}

N or more matches

{N,M}

Between N and M matches

 

 

To demonstrate these rules with another easy example, consider the following regular expression:

[aeiou]{2,4}\+[1-5]*

A string that correctly matches this expression must start with two to four vowels, have a + sign, and terminate with zero or more digits between one and five. The .NET Framework documentation details many more expression modifiers.

Table 4-20 describes a few common (and useful) regular expressions.

Table 4-20. Commonly Used Regular Expressions

Content

Regular Expression

Description

E-mail address*

\S+@\S+\.\S+

Checks for an at (@) sign, dot (.), and only

 

 

allowed nonwhitespace characters.

Password

\w+

Any sequence of word characters (letter, space,

 

 

or underscore).

Specific-length password

\w{4,10}

A password that must be at least four characters

 

 

long but no longer than ten characters.

Advanced password

[a-zA-Z]\w{3,9}

As with the specific-length password, this

 

 

regular expression will allow four to ten total

 

 

characters. The twist is that the first character

 

 

must fall in the range of a–z or A–Z (that is to

 

 

say, it must start with a nonaccented ordinary

 

 

letter).

Another advanced password

[a-zA-Z]\w*\d+\w*

This password starts with a letter character,

 

 

followed by zero or more word characters, a

 

 

digit, and then zero or more word characters.

 

 

In short, it forces a password to contain a

 

 

number somewhere inside it. You could use a

 

 

similar pattern to require two numbers or any

 

 

other special character.

Limited-length field

\S{4,10}

Like the password example, this allows four to

 

 

ten characters, but it allows special characters

 

 

(asterisks, ampersands, and so on).

Social Security number

\d{3}-\d{2}-\d{4}

A sequence of three, two, then four digits,

 

 

with each group separated by a dash. A similar

 

 

pattern could be used when requiring a phone

 

 

number.

 

 

 

*Many different regular expressions of varying complexity can validate e-mail addresses. See http://www. 4guysfromrolla.com/webtech/validateemail.shtml for a discussion of the subject and numerous examples.

C H A P T E R 4 S E R V E R C O N T R O L S

141

The CustomValidator Control

If the validation controls described so far are not flexible or powerful enough for you, and if you need more advanced or customized validation, then the CustomValidator control is what you need. The CustomValidator allows you to execute your custom client-side and server-side validation routines. You can associate these routines with the control so that validation is performed automatically. If the validation fails, the Page.IsValid property is set to false, as occurs with any other validation control.

The client-side and server-side validation routines for the CustomValidator are declared similarly. They both take two parameters: a reference to the validator and a custom argument object. This object provides a Value property that contains the current value of the associated input control (the value you have to validate) and an IsValid property through which you specify whether the input value is valid. If you want to check that a number is a multiple of five, for example, you could use a client-side JavaScript validation routine like this:

<script language="JavaScript">

function EmpIDClientValidate(ctl, args)

{

// the value is a multiple of 5 if the module by 5 is 0 args.IsValid=(args.Value%5 == 0);

}

</script>

To associate this code with the control so that client-side validation is performed automatically, you simply need to set the ClientValidationFunction to the name of the function (in this case, EmpIDClientValidate).

Next, when the page is posted back, ASP.NET fires the CustomValidator.ServerValidate event. You handle this event to perform the same task using C# code. And although the JavaScript logic is optional, you must make sure you include a server-side validation routine to ensure the validation is performed even if the client is using a down-level browser (or tampers with the web-page HTML).

Here’s the C# server-side equivalent of the validation routine shown earlier:

protected void EmpIDServerValidate(object sender, ServerValidateEventArgs args)

{

try

{

args.IsValid = (int.Parse(args.Value)%5 == 0);

}

catch

{

// An error is most likely caused by non-numeric data. args.IsValid = false;

}

}

Finally, here’s an example CustomValidator tag that uses these routines:

<asp:TextBox runat="server" ID="EmpID" /> <asp:CustomValidator runat="server" ControlToValidate="EmpID"

ClientValidationFunction=”EmpIDClientValidate” ErrorMessage="ID must be a multiple of 5" Display="dynamic">*

</asp:CustomValidator>

Tip In ASP.NET 2.0, the CustomValidator includes an additional property named ValidateEmtpyText, which is false by default. However, it’s quite possible you might create a client-side function that attempts to assess empty values. If so, set ValidateEmtpyText to true to give the same behavior to your server-side event handler.

142 C H A P T E R 4 S E R V E R C O N T R O L S

The ValidationSummary Control

The ValidationSummary control doesn’t perform any validation. Instead, it allows you to show a summary of all the errors in the page. This summary displays the ErrorMessage value of each failed validator. The summary can be shown in a client-side JavaScript message box (if the ShowMessageBox property is true) or on the page (if the ShowSummary property is true). You

can set both ShowMessageBox and ShowSummary to true to show both types of summaries, since they are not exclusive. If you choose to display the summary on the page, you can choose a style with the DisplayMode property (possible values are SingleParagraph, List, and BulletList). Finally, you can set a title for the summary with the HeaderText property.

The control declaration is straightforward:

<asp:ValidationSummary runat="server" ID="ValidationSum" ShowSummary="true" DisplayMode="BulletList" HeaderText="<b>Please review the following errors:</b>"

/>

Figure 4-13 shows an example with a validation summary that displays a bulleted summary on the page and in a message box.

Figure 4-13. The validation summary

C H A P T E R 4 S E R V E R C O N T R O L S

143

Using the Validators Programmatically

As with all other server controls, you can programmatically read and modify the properties of a validator. To access all the validators on the page, you can iterate over the Validators collection of the current page.

In fact, this technique is already demonstrated in the sample page shown in Figures 4-11 and 4-12. This page provides four check boxes that allow you to test the behavior of the validators with different options. When a check box is selected, it causes a postback. The event handler iterates over all the validators and updates them according to the new options, as shown here:

protected void Options_Changed(object sender, System.EventArgs e)

{

foreach (BaseValidator valCtl in Page.Validators)

{

valCtl.Enabled=EnableValidators.Checked; valCtl.EnableClientScript = EnableClientSide.Checked;

}

ValidationSum.ShowMessageBox = ShowMsgBox.Checked; ValidationSum.ShowSummary = ShowSummary.Checked;

}

You can use a similar technique to perform custom validation. The basic idea is to add a button with CausesValidation set to false. When this button is clicked, manually validate the page or just specific validators using the Validate() method. Then examine the IsValid property and decide what to do.

The next example uses this technique. It examines all the validation controls on the page by looping through the Page.Validators collection. Every time it finds a control that hasn’t validated successfully, it retrieves the invalid value from the input control and adds it to a string. At the end of this routine, it displays a message that describes which values were incorrect. This technique adds a feature that wouldn’t be available with automatic validation, which uses the static ErrorMessage property. In that case, it isn’t possible to include the actual incorrect values in the message.

protected void cmdOK_Click(Object sender, EventArgs e)

{

// Validate the page. this.Validate();

if (!this.IsValid)

{

string errorMessage = "<b>Mistakes found:</b><br />";

// Create a variable to represent the input control. TextBox ctrlInput;

// Search through the validation controls. foreach (BaseValidator ctrl in this.Validators)

{

if (!ctrl.IsValid)

{

errorMessage += ctrl.ErrorMessage + "<br />";

ctrlInput = (TextBox)this.FindControl(ctrl.ControlToValidate); errorMessage += " * Problem is with this input: "; errorMessage += ctrlInput.Text + "<br />";

}

}

lblMessage.Text = errorMessage;

}

}

144 C H A P T E R 4 S E R V E R C O N T R O L S

This example uses an advanced technique: the Page.FindControl() method. It’s required because the ControlToValidate property is just a string with the name of a control, not a reference to the actual control object. To find the control that matches this name (and retrieve its Text property), you need to use the FindControl() method. Once the code has retrieved the matching text box, it can perform other tasks such as clearing the current value, tweaking a property, or even changing the text box color.

Validation Groups

In more complex pages, you might have several distinct groups of pages, possibly in separate panels. In these situations, you may want to perform validation separately. For example, you might create a form that includes a box with login controls and a box underneath it with the controls for registering a new user. Each box includes its own submit button, and depending on which button is clicked, you want to perform the validation just for that section of the page.

ASP.NET 2.0 enables this scenario with a new feature called validation groups. To create a validation group, you need to put the input controls and the CausesValidation button controls into the same logical group. You do this by setting the ValidationGroup property of every control with the same descriptive string (such as “Form1” or “Login”). Every button control that provides a CauseValidation property also includes the ValidationGroup property. All validators acquire the ValidationGroup by inheriting from the BaseValidator class.

For example, the following page defines two validation groups, named Group1 and Group2:

<form id="form1" runat="server"> <div>

<asp:Panel ID="Panel1" runat="server">

<asp:TextBox ID="TextBox1" ValidationGroup="Group1" runat="server" /> <asp:RequiredFieldValidator ID="RequiredFieldValidator1" ErrorMessage="*Required" ValidationGroup="Group1"

runat="server" ControlToValidate="TextBox1" /> <asp:Button ID="Button1" Text="Validate Group1" ValidationGroup="Group1" runat="server" />

</asp:Panel> <br />

<asp:Panel Height="94px" ID="Panel2" runat="server" Width="125px"> <asp:TextBox ID="TextBox2" ValidationGroup="Group2" runat="server" />

<asp:RequiredFieldValidator ID="RequiredFieldValidator2" ErrorMessage="*Required" ValidationGroup="Group2" ControlToValidate="TextBox2" runat="server" /> <asp:Button ID="Button2" Text="Validate Group2" ValidationGroup="Group2" runat="server" />

</asp:Panel>

</div>

</form>

Figure 4-14 shows the page. If you click the first button, only the first text box is validated. If you click the second button, only the second text box is validated.

An interesting scenario is if you add a new button that doesn’t specify any validation group. In this case, the button validates every control that isn’t explicitly assigned to a named validation group. In this case, no controls fit the requirement, so the page is posted back successfully and deemed to be valid. If you want to make sure a control is always validated, regardless of the validation group of the button that’s clicked, you’ll need to create multiple validators for the control, one

for each group (and one with no validation group). Alternatively, you might choose to manage complex scenarios such as these using server-side code.

C H A P T E R 4 S E R V E R C O N T R O L S

145

Figure 4-14. Grouping controls for validation

In your code, you can work with the validation groups programmatically. You can retrieve the controls in a given validator group using the Page.GetValidators() method. Just pass the name of the group as the first parameter. You can then loop through the items in this collection and choose which ones you want to validate, as shown in the previous section.

Another option is to use the Page.Validate() method and specify the name of the validation group. For example, using the previous page, you could create a button with no validation group assigned and respond to the Click event with this code:

protected void cmdValidateAll_Click(object sender, EventArgs e)

{

Label1.Text = "Valid: " + Page.IsValid.ToString(); Page.Validate("Group1");

Label1.Text += "<br />Group1 Valid: " + Page.IsValid.ToString(); Page.Validate("Group2");

Label1.Text += "<br />Group2 Valid: " + Page.IsValid.ToString();

}

The first Page.IsValid check will return true, because the validators in the two groups weren’t validated. After validating the first group, the Page.IsValid property will return true or false, depending on whether there is text in TextBox1. The same is true for the second group, only now you’re checking for text in TextBox2.

The ASP.NET Rich Controls

Rich controls are web controls that model complex user interface elements. Although there isn’t a strict definition for rich controls, the term commonly describes web controls that provide an object model that is distinctly separate from the underlying HTML representation. A typical rich control can often be programmed as a single object (and defined with a single control tag) but renders itself with a complex sequence of HTML elements and may even use client-side JavaScript.

To understand the difference, consider the Table control and the Calendar control. When you program with the Table control, you use objects that provide a thin wrapper over HTML table elements such as <table>, <tr>, and <td>. The Table control isn’t considered a rich control. On the other hand, when you program with the Calendar, you work in terms of days, months, and selection ranges—concepts that have no direct correlation to the HTML markup that the Calendar renders. For that reason, the Calendar is considered a rich control.

Tip

146 C H A P T E R 4 S E R V E R C O N T R O L S

ASP.NET includes numerous rich controls that are discussed elsewhere in this book, including data-based list controls, security controls, and controls tailored for web portals. The following list identifies the rich controls that don’t fall into any specialized category:

AdRotator: A banner ad that displays one out of a set of images based on a predefined scheduled that’s saved in an XML file.

Calendar: A calendar that displays and allows you to move through months and days and to select a date or a range of days.

MultiView, View, and Wizard: You can think of these controls as more advanced panels that let you switch between groups of controls on a page. The Wizard control even includes builtin navigation logic. You’ll learn about these controls in Chapter 16.

Substitution: This control is really a placeholder that allows you to customize ASP.NET’s output caching feature, which you’ll tackle in Chapter 11.

TreeView: This is the most impressive of the rich controls. It allows you to show a hierarchical tree of items, perhaps as a data-bound list (see Chapter 12) or a navigational control (see Chapter 16).

Xml: Takes an XML file and an XSLT stylesheet file as input and displays the resulting HTML in a browser. You’ll learn about the Xml control in Chapter 12.

The rich controls in this list all appear in the Standard tab of the Visual Studio Toolbox.

The Internet contains many hubs for control sharing. One such location is Microsoft’s own ASP.NET website (http://www.asp.net), which provides a control gallery where developers can submit their own ASP.NET web controls. Some of these controls are free (at least in a limited version), while others require a payment.

The AdRotator Control

The AdRotator randomly selects banner graphics from a list that’s specified in an external XML schedule file.

Before creating the control, it makes sense to define the XML schedule file. Here’s an example:

<Advertisements>

<Ad> <ImageUrl>hdr_logo.gif</ImageUrl>

<NavigateUrl>http://www.apress.com</NavigateUrl> <AlternateText>Apress - The Author's Press</AlternateText> <Impressions>20</Impressions>

<Keyword>books</Keyword>

</Ad>

<Ad>

<ImageUrl>javaOne.gif</ImageUrl>

<NavigateUrl>http://www.sun.com</NavigateUrl> <AlternateText>Java from Sun</AlternateText> <Impressions>20</Impressions> <Keyword>Java</Keyword>

</Ad>

<!-- More ads can go here. --> </Advertisements>

C H A P T E R 4 S E R V E R C O N T R O L S

147

Each <Ad> element has a number of other important properties that configure the link, the image, and the frequency, as described in Table 4-21.

Table 4-21. Advertisement File Elements

Element

Description

ImageUrl

The image that will be displayed. This can be a relative link (a file in the current

 

directory) or a fully qualified Internet URL.

NavigateUrl

The link that will be followed if the user clicks the banner.

AlternateText

The text that will be displayed instead of the picture if it cannot be displayed.

 

This text will also be used as a tooltip in some newer browsers.

Impressions

A number that sets how often an advertisement will appear. This number is

 

relative to the numbers specified for other ads. For example, a banner with the

 

value 10 will be shown twice as often as the banner with the value 5.

Keyword

A keyword that identifies a group of advertisements. This can be used for

 

filtering. For example, you could create ten advertisements and give half of

 

them the keyword Retail and the other half the keyword Computer. The web

 

page can then choose to filter the possible advertisements to include only one

 

of these groups.

 

 

The actual AdRotator class provides a limited set of properties. You specify both the appropriate advertisement file in the AdvertisementFile property and the type of window that the link should follow in the Target property. You can also set the KeywordFilter property so that the banner will be chosen from entries that have a specific keyword.

Here’s an example that opens the link for an advertisement in a new window:

<asp:AdRotator runat="server" AdvertisementFile="Ads.xml" Target="_blank" />

Figure 4-15 shows the AdRotator control. Try refreshing the page. When you do, you’ll see that a new advertisement is randomly selected each time.

Figure 4-15. The AdRotator control

Additionally, you can react to the AdRotator.AdCreated event. This occurs when the page is being created and an image is randomly chosen from the file. This event provides you with information about the image that you can use to customize the rest of your page.