ControlFreak
LANGUAGES:VB.NET
ASP.NETVERSIONS: 1.x | 2.0
Validate User-entered Data
Protect Your Database from Invalid Data by Using the Built-inASP.NET Validation Controls
By Steve C. Orr
If you haven?t familiarized yourself with the validationcontrols in ASP.NET, it?s time to learn. The functionality is far too powerfulto ignore. If you let people enter three-digit ZIP codes, two-digit phonenumbers, and other such nonsense, then over time your database will becomecluttered with garbage beyond all hope of repair. It?s sad to see a perfectlygood application go down in such a needlessly gruesome way. It doesn?t have tobe like that. These controls are a snap to use and will take care of nearly allyour data validation needs ? with little effort on your part.
Make Important Fields Mandatory
One of the most basic validation situations you?ll runacross is to ensure the user has filled in all required values. A billingaddress without a city or ZIP code simply isn?t useful. TheRequiredFieldValidator Web control is what you need for a situation such asthis. It, like the rest of the validation controls mentioned in this article,comes standard with Visual Studio.NET, and can be found in the Web Formssection of your toolbox.
A typical RequiredFieldValidator control is defined in anASPX file with a definition similar to this:
<asp:RequiredFieldValidatorid="RequiredFieldValidator1"
runat="server"ErrorMessage="This field is required!"
ControlToValidate="TextBox1"></asp:RequiredFieldValidator>
To see such a control in action, simply start a new Webapplication in Visual Studio.NET and drag a textbox, a RequiredFieldValidatorcontrol, and a button onto your Web Form. Set the ControlToValidate property ofthe RequiredFieldValidator control to the name of the textbox (TextBox1 bydefault). Now run the project and click on the button without typing anythingin the textbox. You?ll notice that the RequiredFieldValidator control springsinto action and prevents the postback from occurring and displays a red errormessage. The default message is not friendly, so you should stop theapplication and improve the message by changing the ErrorMessage property ofthe RequiredFieldValidator control to more appropriate text.
Preventing the postback from occurring when there?sinvalid data is an efficient use of client-side script. This client-side scriptis generated automatically, so you might never even notice it?s there. However,not all browsers support client-side script, and some users may have itdisabled as a security precaution. Therefore, server-side validation is alsodone (automatically) as a failsafe.
Now things work pretty nicely. The user gets a friendlynotification when they fail to enter an important value that is required byyour application. The only details left are really a matter of polish, and suchdetails can be the difference between an application that merely works, and onethat impresses people.
Before the user has clicked the button, there is noindication that the field is required. Sure, they?ll be notified after they hitthe button, but this can waste precious seconds of the user?s time. A standardsolution is to display an asterisk (*) next to the field, or some other labelto visually identify the field as required. To do this, you only need to setthe Text property of the RequiredFieldValidator control.
Another notable property of the RequiredFieldValidatorcontrol is InitialValue. This allows you to place some text into the control tobe validated, and have it be recognized by the validator control as a non-user-enteredvalue. This tends to be useful in situations where screen real estate iscramped and precious, and you?d rather not put an identifying label next to thecontrol. Figure 1 illustrates this situation. This technique also works greatwith DropDownLists, so that you can select a default ?Choose from below? itemand still ensure the user selects an item from the list.
Figure 1: The InitialValue propertyof the RequiredFieldValidator control lets you define an initial message in thecontrol without setting off the validation error message.
Tip: Imagine for a moment that you have another unrelatedbutton on the Web form, perhaps a Help button. You probably don?t want thisbutton click event to be prevented by invalid data. Therefore, you should setthe CausesValidation property of the Help button to false. Now the user can gethelp at any time, whether they?ve entered valid data yet or not.
Field Comparison
Sometimes you need to compare two fields to each other toensure validity. Sometimes the values need to match. Sometimes you need to makesure they?re different from each other. Sometimes you need to make sure onevalue is greater than the other, and so on. The CompareValidator is an idealtool for handling these kinds of validation.
One common example is a new user registration page. Theuser needs to type in their new password, and then they need to type it againto confirm they know their password and typed it correctly. In this case, bothpassword fields must match or else the data is considered to be in an invalidstate. Such a page is illustrated in Figure 2.
Figure 2: This Web form shows all sixvalidation controls in action: RequiredFieldValidator, CompareValidator,RangeValidator, RegularExpressionValidator, CustomValidator, andValidationSummary.
This control (like all the validation controls) has aControlToValidate property that specifies the primary validation field on the Webform. The CompareValidator control also has a ControlToCompare property thatspecifies a second control to which the ControlToValidate field can becompared. If you wish to compare the control to a value that is not present inanother control on the form, you should use the ValueToCompare property insteadof the ControlToCompare property:
<asp:CompareValidator id="CompareValidator1"runat="server"
ControlToValidate="txtPassword1"
ControlToCompare="txtPassword2"Operator="Equal"
ErrorMessage="Passwordsdon't match"></asp:CompareValidator>
Another unique property of this control is the Operatorproperty. It specifies what kind of comparison will be done between the twocontrols. A value of ?Equal? specifies that the values of the two controls mustbe identical. The other possible values are: NotEqual, GreaterThan,GreaterThanEqual, LessThan, LessThanEqual, and DataTypeCheck. They are allfairly self-explanatory, except perhaps DataTypeCheck. When this is selected,it is used in conjunction with the Type property, which can contain values ofString, Integer, Double, Date, or Currency. If the value in theControlToValidate field cannot be converted to the chosen data type, then it isconsidered invalid and the value of the ErrorMessage property will be displayedto the user.
Accept Data within a Specified Range
It is often necessary to ensure a user-entered value iswithin a reasonable range. For example, if somebody claims to be 574 years old,then you can be fairly certain they?ve made a mistake. The RangeValidatorcontrol comes into play for just this type of situation. It has a MinimumValueproperty and a MaximumValue property to specify the lower and upper bounds ofacceptable values:
<asp:RangeValidator id="RangeValidator1"runat="server"
ControlToValidate="TextBox1"ErrorMessage="Invalid Age"
MinimumValue="18"MaximumValue="120" Type="Integer">
</asp:RangeValidator>
The RangeValidator control has a Type property that cancontain values of String, Integer, Double, Date, or Currency. This property isimportant because it specifies how the data will be interpreted. The value thatthe user entered, along with the MinimumValue and MaximumValue properties, areall converted to this data type before they are compared. (If they cannot beconverted to the specified data type, the data is considered invalid and theErrorMessage text will be displayed.)
If you set the MaximumValue field to 120 and theMinimumValue field to 18 and ignore the Type property, the control will throw acompile-time error specifying that the MaximumValue property must be greaterthan the MinimumValue property. ?But 120 is greater than 18!? you?ll say. Ahh,when they are compared as numbers this is true, but you forgot to set the Typeproperty to Integer and left it at the default of String. The string ?18? isindeed greater than the string ?120?, thus causing the potentially confusingerror.
Validate with Regular Expressions
When your data needs to get a bit more complex, you needto break out some new tricks. Although there is no masked edit control builtinto ASP.NET 1.x, the RegularExpressionValidator is the next best thing. RegularExpressions are a way to describe a string pattern, such as an e-mail address. Thereare many ways to incorrectly type an e-mail address, so regular expressions arethe most efficient way to make sure all your bases are covered. The RegularExpressionValidatorcontrol has a ValidationExpression property that holds the regular expressionthat will be compared against the value the user enters into theControlToValidate control. In the Visual Studio.NET property window for theRegularExpressionValidator control you?ll find an ellipsis (...) button in theValidationExpression property. Click the button to choose from a list of themost common regular expressions, which contains values for phone numbers, e-mailaddresses, Social Security numbers, ZIP codes, and more. If you don?t find theexpression you need, I suggest you look for the one you need at http://www.regexplib.com.
You can of course design your own custom regularexpressions to match any string pattern you can imagine, although it might bequite a learning experience if you?re not already familiar with regularexpressions:
<asp:RegularExpressionValidator
id="RegularExpressionValidator1"runat="server"
ControlToValidate="TextBox1"
ValidationExpression="\d{5}(\d{4})?"
ErrorMessage="InvalidZip Code!">
</asp:RegularExpressionValidator>
It?s a deep topic. There are entire books written on thesubject.
Create Custom Validators
I suspect you agree by now that the validation controlsare quite easy to use. Have you noticed all the power that has been describedso far without a single line of code needing to be written? Well, automaticfeatures like these are nice, but there will always be times when you need totake control of the helm and write some custom code. Although the previouslyexplained controls should be able to handle 95% of your validation needs, theCustomValidator control takes care of the rest:
<asp:CustomValidator id="CustomValidator1"runat="server"
ErrorMessage="InvalidPassword"
ControlToValidate="TextBox1"></asp:CustomValidator>
The only unique property of this control is namedClientValidationFunction. As you might suspect, this property is meant to holdthe name of a custom client-side function that will handle client-sidevalidation. This property is optional, and client-side validation can be turnedoff for any of the validation controls by setting the EnableClientScriptproperty to false. The function shown in Figure 3 is an example of a client-sidefunction that validates the number a person entered is an even number.
<script language="vbscript">
<!--
SubClientValidate(source, arguments)
If arguments.Value/2 =CInt(arguments.Value/2) Then
arguments.IsValid=true
Else
arguments.IsValid=false
End If
End Sub
' -->
</script>
Figure 3: Usingthe CustomValidator control to call your own client-side validation functionssuch as this is more efficient than relying on server-side validation alone.
You should always implement server-side validation (justlike the other validation controls do automatically) to be sure validationhappens, even if client-side script is not enabled. For this reason, theCustomValidator control has a server-side event named ServerValidate. Figure 4contains a server-side validation routine that matches the client-sidevalidation routine shown in Figure 3.
'VB.NET
Private Sub CustomValidator1_ServerValidate(ByVal source _
As System.Object, ByVal args _
As System.Web.UI.WebControls.ServerValidateEventArgs) _
Handles CustomValidator1.ServerValidate
If args.Value / 2 =CInt(args.Value / 2) Then
args.IsValid = True
Else
args.IsValid =False
End If
End Sub
Figure 4: Don?tforget to implement a server-side validation function for the CustomValidatorcontrol, because client-side validation alone is not very dependable.
Summarizing Validation Errors
The ValidationSummary control is unlike the othervalidation controls because it doesn?t actually do any validation. Rather, it?smore of a list that can sum up all the validation errors on the page anddisplay them in one place. Alternatively, you can have it pop up a message boxdetailing the various errors. The corresponding Boolean properties of thecontrol are named ShowSummary and ShowMessageBox:
<asp:ValidationSummary id="ValidationSummary1"
runat="server"Width="184px" HeaderText="Error Summary:"
BorderStyle="Dotted"ShowMessageBox="True">
</asp:ValidationSummary>
If you?ve got a complex data entry form that has room formany errors, the ValidationSummary control can be a valuable way to communicatewith the user about what exactly they?ve done wrong as compared with yourexpectations. You can see it in action at the right side of Figure 2. Theoutput is a bit ugly by default, but you can adjust many visual properties tomake it more attractive.
Visions of the Future
The worst limitation about the validation controls inASP.NET 1.x is that you can only validate one group of controls on a page. Forexample, maybe you?ve got a standard newsletter sign-up textbox in the leftmargin of every page and you want to validate the e-mail address they enter(perhaps using the RegularExpressionValidator control). Then, in the middle ofone of your pages, you?ve got some input fields (shipping address fields, forexample) that are required (using the RequiredFieldValidator control). The userenters their e-mail address to sign up for your newsletter and clicks thesubmit button next to it, and they are wrongly halted because they didn?t fillin the completely unrelated shipping address fields.
In ASP.NET 1.x there just isn?t a graceful solution for aconundrum such as this. Luckily, they?ve fixed this annoying problem in ASP.NET2.0 by implementing Validation Groups. Figure 5 illustrates the solution?ssyntax. It defines two standard textboxes, a validator for each, and a buttonfor each. Because the first validator is defined as belonging to Group1, andthe first button is also assigned Group1, only the first validator is executedwhen Group1?s button is clicked. Likewise, only Group2?s validator(s) will befired when Group 2?s button is clicked.
<asp:textbox id="Email" runat="server"/>
<asp:textbox id="ShippingAddress"runat="server"/>
<asp:RegularExpressionValidatorValidationGroup="Group1"
id="RegularExpressionValidator1"runat="server"
ErrorMessage="Invalid Email Address"
ControlToValidate="txtEmail" ValidationExpression=
"\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*">
</asp:RegularExpressionValidator></P>
<asp:requiredfieldvalidator ValidationGroup="Group2"
ErrorText="Need toFill in Value! "
ControlToValidate="ShippingAddress"
runat="server"/>
<asp:button text="Group1"ValidationGroup="Group1"
runat="server"/>
<asp:button text="Group2"ValidationGroup="Group2"
runat="server"/>
Figure 5: ValidationGroups in ASP.NET 2.0 will solve the frustrating dilemma of having unrelatedsets of controls interfere with each other?s validation.
Tidbits
If needed, you can mix and match controls to (for example)mark a field as required AND verify it?s within a specified range. For thisscenario, simply use two validation controls (the RequiredFieldValidator andthe RangeValidator) and give them both the same ControlToValidate.
The Display property that most of the validation controlsshare uses a bit of DHTML to determine the details about how exactly avalidation message is shown and hidden at run time. If you set this property tothe Static enumeration, space will be reserved on the page to display the errormessage. Conversely, when the property is set to Dynamic, page content will bemoved around as needed to make room for the validation error message when itneeds to be displayed. It can be slightly jarring for some users to have pagecontent moving around on them as they are typing, so I suggest using a StaticDisplay in most cases.
The ASP.NET validation controls are powerful, flexible,and easy to use. With little or no code you can bulletproof your data entryforms to ensure data integrity throughout. Small efforts like these can makethe difference between a database application that lives for decades, and onethat gradually decays beyond repair.
The sample code inthis article is available for download.
Steve C. Orr is anMCSD and a Microsoft MVP in ASP.NET. He?s been developing software solutionsfor leading companies in the Seattlearea for more than a decade. When he?s not busy designing software systems orwriting about them, he can often be found loitering at local user groups andhabitually lurking in the ASP.NET newsgroup. Find out more about him at http://Steve.Orr.netor e-mail him at mailto:Steve@Orr.net.