asp.netNOW Q&A
LANGUAGES: VB .NET
TECHNOLOGIES: Validator Controls
Work With Multiple Validator Controls
Learn to set up dependencies between controls, as well as validate those controls.
By Josef Finsel
Q: I have a form, with two fields that relate to each other: a radio box for country (U.S. or otherwise) and a textbox for a U.S. ZIP code. I want to ensure that if they have the U.S. radio button selected, they also have a valid U.S. ZIP code. Validating the ZIP code with a regular expression is easy enough. The problem is if there is no value in the ZIP code box, a custom validation control still considers it valid. And I can't put a required control on it, because it isn't always required. Any suggestions?
A: Validator controls come in many different flavors. Their purpose is to provide an easy and consistent way of validating data in other controls (read Steven Smith's article, "Master ASP.NET Validator Controls," http://www.aspnetpro.com/features/2002/07/asp200207vd_f/asp200207vd_f.asp, to get a grounding in validator controls). When you mix two controls together for validation, it gets a little trickier. Basically, you want to take two controls on the page: a RadioButtonList for the country choice, and a TextBox for the ZIP code. Then you must determine whether the ZIP code is required. So you're going to end up with pseudo code that looks like this:
IF Country=US AND ZipCode = "" then
Valid
ELSE
Invalid
This sounds like just the thing for a CustomValidation control ... except it doesn't work. That merely gives us an opportunity, however, to make this work better. First take a look at the normal controls we are going to put on the page (see Figure 1). It's nothing too exciting - a RadioButtonList, a TextBox, and a button to submit it all.
<form runat="server" ID="Form1">
<asp:RadioButtonList id="rbCountry" runat="server"
BorderStyle="Solid">
<asp:ListItem Value="US">US</asp:ListItem>
<asp:ListItem Value="Canada">Canada</asp:ListItem>
<asp:ListItem Value="Other">Other</asp:ListItem>
</asp:RadioButtonList></P>
<P>If US or Canada, enter your ZipCode:<br></P>
<P><asp:TextBox id="txtZipCode" runat="server" /></P>
<p><asp:Button text="Validate" runat="server" ID="Button1"
onclick="ValidateBtn_OnClick" /></p>
</form>
Figure 1. This is what the page looks like before the CustomValidator control is added.
The first thing you want to add is a CustomValidator control. In most circumstances, you'd add the control with code like this:
<asp:CustomValidator id="CustomValidator1" runat="server"
OnServerValidate="ServerValidate" Display="Static"
Font-Name="verdana" Font-Size="10pt"
ControlToValidate="txtZipCode">You must enter a zip code
if you live in the US or Canada</asp:CustomValidator>
The OnServerValidate="ServerValidate" defines a sub or function within your codebehind, which is called to validate whether control your checking is valid. It's important to note that it can only work with the one control - it can't really reach out and check the status of other controls. This means simply putting an IsValid check in the button press event won't work because the OnServerValidate code can't check other controls. It doesn't mean, however, that we can't use the Validator control. The trick to cross-checking controls with validation is to step outside the normal process. You remove the OnServerValidate property, then, within the button press, you handle the validating as well as throw the exception:
If rbCountry.SelectedItem.ToString = "US" And _
txtZipCode.Text.Trim.Length() = 0 Then
CustomValidator1.IsValid = False
lblOutput.Text = "Invalid data"
Else
CustomValidator1.IsValid = True
lblOutput.Text = "Valid data"
End If
As long as you're doing this, you might as well determine whether the ZIP code is formatted correctly:
If (rbCountry.SelectedItem.ToString = "US" Or _
rbCountry.SelectedItem.Text = "Canada") Then
If txtZipCode.Text.Trim.Length() = 0 Then
CustomValidator1.IsValid = False
Else
Dim strRegExpZipCode As String
Select Case rbCountry.SelectedItem.Text
Case "US"
strRegExpZipCode = "^((\d{5}-\d{4})|(\d{5}))$"
Case "Canada"
strRegExpZipCode = "^([A-Z]\d[A-Z]\s\d[A-Z]\d)$"
End Select
If Regex.IsMatch(txtZipCode.Text, strRegExpZipCode) Then
CustomValidator1.IsValid = True
Else
CustomValidator1.IsValid = False
End If
End If
Else
CustomValidator1.IsValid = True
End If
The final point of note is that this doesn't keep you from checking Page.IsValid. The final code, which is available for download, also contains a RequiredFieldValidator for the Country RadioButtonList, and the end of the Button Press event actually checks Page.IsValid to determine whether or not the page is filled in completely.
Keep your ASP.NET questions coming at [email protected].
The sample code referenced in this article is available for download.
Josef Finsel is a software consultant with a global consulting firm and specializes in .NET and SQL Server. He has published a number of VB, .NET, and SQL Server-related articles, and when he isn't hanging around the aspnetpro forums, you can find him working on the syntax for FizzBin.NET, a programming language that works the way programmers have always suspected. He's also author of The Handbook for Reluctant Database Administrators (Apress).