Add a CustomValidator
control to the drop-down
list, along with some client-side JavaScript to validate the
selection. Next, implement an event handler for the
CustomValidator
control’s
ServerValidate
event. Finally, check the
Page.IsValid
property in the event handler for the
control that completes the user’s entry for the
page.
In the .aspx
file:
Add a CustomValidator
control for each drop-down
list where you must verify that an item has been selected.
Add JavaScript to validate the selection on the client side.
Add Save and Cancel (or equivalently named) buttons.
Set the Save button’s
CausesValidation
attribute to
True
to have validation performed when the button
is clicked (set it to False
for the Cancel
button).
In the code-behind class for the page, use the .NET language of your choice to:
Add an event handler for the CustomValidator
control’s ServerValidate
event
whose purpose is to provide the server-side validation to ensure an
item has been selected.
Add code to the event handler for the Save button’s
click event to check the Page.IsValid
property and
verify that all validation was successful (see Recipe 2.1 for details).
Figure 2-9 shows a typical form with normal output
prior to data entry. Figure 2-10 shows the form with
validation errors. Example 2-7 through
Example 2-9 show the .aspx
and
code-behind files for our application that implements the solution.
This recipe involves using a CustomValidator
control to verify that an item has been selected in a drop-down list.
But the approach we advocate is a bit out of the ordinary for a
couple of reasons. First, by implementing validation via client-side
JavaScript, it allows errors to be detected on the client, thus
avoiding unnecessary round trips to the server for server-side
validation.
Besides using a CustomValidator
control, this
application also uses validation controls from all of the previous
recipes combined, specifically
RequiredFieldValidator
,
RangeValidator
,
CompareValidator
, and
RegularExpressionValidator
. Combining validators
of various types is typical when performing validation on a complex
form.
Second, instead of displaying an error message at each control, this
example shows how to use a ValidationSummary
control to provide a list of all errors on the page in one place.
This approach is very useful for a
“busy” form.
To implement the solution, the ControlToValidate
attribute must be set to the drop-down list you will be validating.
In our case, it is set to ddCountry
:
<asp:CustomValidator id="valItemSelected" runat="server"
ControlToValidate="ddCountry"
ClientValidationFunction="isItemSelected"
CssClass="AlertText"
Display="Dynamic"
EnableClientScript="True"
ErrorMessage="Country Must Be Selected">
<img src="images/arrow_alert.gif" />
</asp:CustomValidator>
The ClientValidationFunction
attribute must be set
to the name of the client JavaScript function that will perform the
client-side validation, which is done to ensure that an item has been
selected from the drop-down:
<asp:CustomValidator id="valItemSelected" runat="server"
ControlToValidate="ddCountry"
ClientValidationFunction="isItemSelected"
CssClass="AlertText"
Display="Dynamic"
EnableClientScript="True"
ErrorMessage="Country Must Be Selected">
<img src="images/arrow_alert.gif" />
</asp:CustomValidator>
A client script block must be added to the page containing the
function named in the ClientValidationFunction
attribute of the CustomValidator
, as shown in
Example 2-7. The function must have source and
argument parameters. When the function is called, the source will be
set to a reference to the validator that called the function. In this
case, it is the "valItemSelected
" validator.
The arguments parameter is a structure containing two elements:
Value
and IsValid
.
Value
contains the current value of the control
that is being validated. In this case, it is the value of the
selected item in the drop-down list. In our example, three entries
are added to the drop-down list, with the first entry being the
"Select Country
" instruction with a value of 0.
All legitimate selections from the drop-down contain values greater
than 0; therefore, if the value of arguments.Value
is less than 1, no selection has been made, and the value of
arguments.IsValid
is set to
False
to indicate a validation failure. If
arguments.Value
is greater than 0, then a
selection has been made, and arguments.IsValid
is
set to True
to indicate the validation passed.
The EnableClientScript
attribute is set to
True
or False
according to how
you want validation to be performed. Setting the attribute to
True
causes validation to be performed on the
client and again on the server when the page is submitted. Setting
the attribute to False
causes validation to be
performed only on the server when the form is submitted. In our
example we are providing client-side JavaScript, so it must be set to
True
:
<asp:CustomValidator id="valItemSelected" runat="server"
ControlToValidate="ddCountry"
ClientValidationFunction="isItemSelected"
CssClass="AlertText"
Display="Dynamic"
EnableClientScript="True"
ErrorMessage="Country Must Be Selected">
<img src="images/arrow_alert.gif" />
</asp:CustomValidator>
Rather than outputting an error message at each control, as was done
in all the previous examples in this chapter, we’ve
added a ValidationSummary
control to the form in
this example to provide in one place a summary of all the errors on
the form. When a validation summary is being used, an error message
is no longer required between the start and end tags of the validator
element. Instead, the ErrorMessage
attribute of
the validator is set to the error message to display. To provide
visual feedback of which control has an error, an arrow image is
inserted between the start and end tags of the validator element in
our example:
<asp:CustomValidator id="valItemSelected" runat="server"
ControlToValidate="ddCountry"
ClientValidationFunction="isItemSelected"
CssClass="AlertText"
Display="Dynamic"
EnableClientScript="True"
ErrorMessage="Country Must Be Selected">
<img src="images/arrow_alert.gif" />
</asp:CustomValidator>
The DisplayMode
attribute of the
asp:ValidationSummary
control defines how the
summary is displayed. Valid values are BulletList
,
List
, and SingleParagraph
.
BulletList
will generate a bulleted list of the
errors, which is what we’ve chosen for our example.
List
will generate the same list as the
BulletList
setting but without the bullets.
SingleParagraph
generates a single HTML paragraph
containing all of the error information. The
HeaderText
attribute is set to the title placed at
the top of the list of errors.
<asp:ValidationSummary id="vsErrors" Runat="server"
CssClass="AlertText"
DisplayMode="BulletList"
EnableClientScript="True"
HeaderText="Error Summary" />
The sample application’s code-behind includes an
event handler for the CustomValidator
control’s ServerValidate
event,
as shown in Example 2-8 (VB) and Example 2-9 (C#). This event handler provides the
server-side validation to ensure a country has been selected using
the same technique implemented in the client script.
The code-behind also includes an event handler for the Save button’s click event. This event handler checks to make sure the page is valid (all validation passed) and then performs the processing of the form data.
Recipe 2.1; Recipe 2.2; Recipe 2.3; Recipe 2.4
Example 2-7. Form with selection validation (.aspx)
<%@ Page Language="vb" AutoEventWireup="false" Codebehind="CH02CustomSelectionValidationVB.aspx.vb" Inherits="ASPNetCookbook.VBExamples.CH02CustomSelectionValidationVB" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title>Custom Selection Validator</title> <link rel="stylesheet" href="css/ASPNetCookbook.css"><script language="javascript">
<!--
function isItemSelected(source, arguments)
{
if (arguments.Value < 1)
{
arguments.IsValid = false;
}
else
{
arguments.IsValid = true;
}
}
//-->
</script>
</head> <body leftmargin="0" marginheight="0" marginwidth="0" topmargin="0"> <form id="frmValidation" method="post" runat="server"> <table width="100%" cellpadding="0" cellspacing="0" border="0"> <tr> <td align="center"> <img src="images/ASPNETCookbookHeading_blue.gif"> </td> </tr> <tr> <td class="dividerLine"> <img src="images/spacer.gif" height="6" border="0"></td> </tr> </table> <table width="90%" align="center" border="0"> <tr> <td><img src="images/spacer.gif" height="10" border="0"></td> </tr> <tr> <td align="center" class="PageHeading"> Custom Validation (VB) </td> </tr> <tr> <td><img src="images/spacer.gif" height="10" border="0"></td> </tr> <tr> <td align="center"> <table border="0"> <tr> <td colspan="2" align="left"> <asp:ValidationSummary id="vsErrors" Runat="server" CssClass="AlertText" DisplayMode="BulletList" EnableClientScript="True" HeaderText="Error Summary" /> </td> </tr> <tr> <td class="LabelText">First Name: </td> <td> <asp:TextBox id="txtFirstName" Runat="server" Columns="30" CssClass="LabelText" /> <asp:RequiredFieldValidator id="rfvFirstName" Runat="server" ControlToValidate="txtFirstName" CssClass="AlertText" Display="Dynamic" EnableClientScript="True" ErrorMessage="First Name Is Required"> <img src="images/arrow_alert.gif"> </asp:RequiredFieldValidator> </td> </tr> <tr> <td class="LabelText">Last Name: </td> <td> <asp:TextBox id="txtLastName" Runat="server" Columns="30" CssClass="LabelText" /> <asp:RequiredFieldValidator id="rfvLastName" Runat="server" ControlToValidate="txtLastName" CssClass="AlertText" Display="Dynamic" EnableClientScript="True" ErrorMessage="Last Name Is Required"> <img src="images/arrow_alert.gif"> </asp:RequiredFieldValidator> </td> </tr> <tr> <td class="LabelText">Age: </td> <td> <asp:TextBox id="txtAge" Runat="server" Columns="30" CssClass="LabelText" /> <asp:RequiredFieldValidator id="Requiredfieldvalidator1" Runat="server" ControlToValidate="txtAge" CssClass="AlertText" Display="Dynamic" EnableClientScript="True" ErrorMessage="Age Is Required"> <img src="images/arrow_alert.gif"> </asp:RequiredFieldValidator> <asp:RangeValidator id="rvAge" Runat="server" ControlToValidate="txtAge" CssClass="AlertText" Display="Dynamic" EnableClientScript="True" MinimumValue="18" MaximumValue="99" Type="Integer" ErrorMessage="Age Must Be Between 18 and 99"> <img src="images/arrow_alert.gif"> </asp:RangeValidator> </td> </tr> <tr> <td class="LabelText">Country: </td> <td> <asp:DropDownList id="ddCountry" Runat="server" > <asp:ListItem Selected="True" Value="0">----- Select Country -----</asp:ListItem> <asp:ListItem Value="1">Canada</asp:ListItem> <asp:ListItem Value="2">United States</asp:ListItem> </asp:DropDownList><asp:CustomValidator id="valItemSelected" runat="server"
ControlToValidate="ddCountry"
ClientValidationFunction="isItemSelected"
CssClass="AlertText"
Display="Dynamic"
EnableClientScript="True"
ErrorMessage="Country Must Be Selected">
<img src="images/arrow_alert.gif" />
</asp:CustomValidator>
</td> </tr> <tr> <td class="LabelText">Email Address: </td> <td> <asp:TextBox id="txtEmailAddress" Runat="server" Columns="30" CssClass="LabelText" /> <asp:requiredfieldvalidator id="rfvEmailAddress" runat="server" controltovalidate="txtEmailAddress" cssclass="AlertText" display="Dynamic" enableclientscript="True"> <img src="images/arrow_alert.gif"> </asp:requiredfieldvalidator> <asp:RegularExpressionValidator id="revEmailAddress" Runat="server" ControlToValidate="txtEmailAddress" CssClass="AlertText" Display="Dynamic" EnableClientScript="True" ValidationExpression="w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*" ErrorMessage="Invalid Email Address"> <img src="images/arrow_alert.gif"> </asp:RegularExpressionValidator> </td> </tr> <tr> <td class="LabelText">Password: </td> <td> <asp:TextBox id="txtPassword1" Runat="server" TextMode="Password" Columns="30" CssClass="LabelText" /> <asp:RequiredFieldValidator id="rfvPassword1" Runat="server" ControlToValidate="txtPassword1" CssClass="AlertText" Display="Dynamic" EnableClientScript="True" ErrorMessage="Password Is Required"> <img src="images/arrow_alert.gif"> </asp:RequiredFieldValidator> </td> </tr> <tr> <td class="LabelText">Re-enter Password: </td> <td> <asp:TextBox id="txtPassword2" Runat="server" TextMode="Password" Columns="30" CssClass="LabelText" /> <asp:RequiredFieldValidator id="rvPassword2" Runat="server" ControlToValidate="txtPassword2" CssClass="AlertText" Display="Dynamic" EnableClientScript="True" ErrorMessage="Re-Entered Password Is Required"> <img src="images/arrow_alert.gif"> </asp:RequiredFieldValidator> <asp:CompareValidator ID="cvPassword2" runat="server" ControlToValidate="txtPassword2" ControlToCompare="txtPassword1" CssClass="AlertText" Display="Dynamic" EnableClientScript="True" ErrorMessage="Both Passwords Must Match"> <img src="images/arrow_alert.gif"> </asp:CompareValidator> </td> </tr> <tr> <td colspan="2"> <br> <table align="center" width="50%"> <tr> <td align="center"> <asp:ImageButton id="btnSave" Runat="server" CausesValidation="True" ImageUrl="images/buttons/button_save.gif" /> </td> <td align="center"> <asp:ImageButton id="btnCancel" Runat="server" CausesValidation="False" ImageUrl="images/buttons/button_cancel.gif" /> </td> </tr> </table> </td> </tr> </table> </td> </tr> </table> </form> </body> </html>
Example 2-8. Form with selection validation code-behind (.vb)
Option Explicit On Option Strict On '----------------------------------------------------------------------------- ' ' Module Name: CH02CustomSelectionValidationVB.aspx.vb ' ' Description: This module provides the code behind for ' CH02CustomSelectionValidationVB.aspx ' '***************************************************************************** Imports System.Web.UI.WebControls Namespace ASPNetCookbook.VBExamples Public Class CH02CustomSelectionValidationVB Inherits System.Web.UI.Page 'controls on form Protected ddCountry As DropDownList Protected WithEvents valItemSelected As CustomValidator Protected WithEvents btnSave As ImageButton '************************************************************************* ' ' ROUTINE: Page_Load ' ' DESCRIPTION: This routine provides the event handler for the page load ' event. It is responsible for initializing the controls ' on the page. '------------------------------------------------------------------------- Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles MyBase.Load If (Not Page.IsPostBack) Then 'Put user code to initialize the page here End If End Sub 'Page_Load '************************************************************************* ' ' ROUTINE: valItemSelected_ServerValidate ' ' DESCRIPTION: This routine provides the event handler for the ' valItemSelected server validate event. It is responsible ' for validating that a country has been selected '-------------------------------------------------------------------------Private Sub valItemSelected_ServerValidate(ByVal source As Object, _
ByVal args As System.Web.UI.WebControls.ServerValidateEventArgs) _
Handles valItemSelected.ServerValidate
If (ddCountry.SelectedIndex < 1) Then
args.IsValid = False
Else
args.IsValid = True
End If
End Sub 'valItemSelected_ServerValidate
'*************************************************************************** ' ' ROUTINE: btnSave_Click ' ' DESCRIPTION: This routine provides the event handler for the save ' button click event. It is responsible for processing the ' form data. '---------------------------------------------------------------------------Private Sub btnSave_Click(ByVal sender As Object, _
ByVal e As System.Web.UI.ImageClickEventArgs) _
Handles btnSave.Click
If (Page.IsValid) Then
'process form data and save as required for application
End If
End Sub 'btnSave_Click
End Class 'CH02CustomSelectionValidationVB End Namespace
Example 2-9. Form with selection validation code-behind (.cs)
//---------------------------------------------------------------------------- // // Module Name: CH02CustomSelectionValidationCS.aspx.cs // // Description: This module provides the code behind for // CH02CustomSelectionValidationCS.aspx // //**************************************************************************** using System; using System.Web.UI; using System.Web.UI.WebControls; namespace ASPNetCookbook.CSExamples { public class CH02CustomSelectionValidationCS : System.Web.UI.Page { // controls on form protected DropDownList ddCountry; protected CustomValidator valItemSelected; protected ImageButton btnSave; //************************************************************************ // // ROUTINE: Page_Load // // DESCRIPTION: This routine provides the event handler for the page // load event. It is responsible for initializing the // controls on the page. //------------------------------------------------------------------------ private void Page_Load(object sender, System.EventArgs e) { // wire the save button click and the item selected validation events this.btnSave.Click += new ImageClickEventHandler(this.btnSave_Click); this.valItemSelected.ServerValidate += new ServerValidateEventHandler(this.valItemSelected_ServerValidate); if (!Page.IsPostBack) { //Put user code to initialize the page here } } // Page_Load //************************************************************************ // // ROUTINE: valItemSelected_ServerValidate // // DESCRIPTION: This routine provides the event handler for the // valItemSelected server validate event. It is // responsible for validating that a country has been // selected //------------------------------------------------------------------------private void valItemSelected_ServerValidate(Object source,
System.Web.UI.WebControls.ServerValidateEventArgs args)
{
if (ddCountry.SelectedIndex < 1)
{
args.IsValid = false;
}
else
{
args.IsValid = true;
}
} // valItemSelected_ServerValidate
//************************************************************************ // // ROUTINE: btnSave_Click // // DESCRIPTION: This routine provides the event handler for the save // button click event. It is responsible for processing // the form data. //------------------------------------------------------------------------private void btnSave_Click(Object sender,
System.Web.UI.ImageClickEventArgs e)
{
if (Page.IsValid)
{
// process form data and save as required for application
}
} // btnSave_Click
} // CH02CustomSelectionValidationCS }