Practical ASP.NET

Validators: The Easy Way To Build Business Rules into Your UI

Validator controls make handling errors and reporting them in the UI easy, but what you may not know is how easy it is to create your own Validator.

Validators are terrific controls but the ones that come with ASP.NET are, well, limited. For most business logic, developers either use the CustomValidator (which lets you insert your own validation code) or bypass the Validator controls altogether which means writing a lot of code that Validators take care of automatically. The right answer is often to create your own Validator to call the validation code in your application.

I had one client who must have collected address information on a dozen pages on several different sites. Since adding the necessary controls and code to all of these pages was really boring, I considered creating an "address user control" that I could drag onto any page. However, user controls can only be used in one project (besides, the client wanted the various controls laid out in different ways on different pages). Instead, I created a new Validator -- the AddressValidator -- and put it in the Toolbox so I could use it on any page in any site.


I've picked the AddressValidator control for this example because it supports checking multiple controls (not just the StreetAddress but also the City, Province/State, Country controls) which might be text boxes or some kind of listing control (drop-down list, radio button lists). This lets me not only show how to handle multiple controls but also to how to list controls in the Properties window.

Creating the Control
Creating a Validation control is relatively straightforward: Create a new project and, from the Web tab, select ASP.NET Server Control (I named my project "PHVValidators"). Once the project is created, rename the default ServerControl1.cs file to the name you want for your control (I used "AddressValidator") and have the class inherit from BaseValidator. You'll also need to change the name of the control in the ToolboxData attribute that appears on the class declaration:

using System;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace PHVValidators
{
  [DefaultProperty("ControlToValidate")]
  [ToolboxData("<{0}:AddressValidator runat=server>
              </{0}:AddressValidator>")]
   public class AddressValidator : 
                    System.Web.UI.WebControls.BaseValidator
 {

All you need to add to the BaseValidator is a test for valid data and any additional properties required to support your validation code.

I'll look at the properties first. For them, I need some fields to hold the names of the controls holding the parts of the address. I also need some properties to capture and hold that data. Since these properties must be set to the name of a control on the page, I'd like to have the property in the Properties window display a drop list of controls on the page. That's easy to do: I just add the TypeConvererAttribute attribute to the property, passing the type of the ValidatedControlConverter. Here's an example of the property to hold the name of the control that with the name of the city:

string cityId = "";

[TypeConverterAttribute(typeof(ValidatedControlConverter))] _
 string CityId
{
    get
   {
       return cityId;
   }
   set
  {
      cityId = value;
   }
}

Validating Data
The only method in the BaseValidator class you must override is the EvaluateIsValid method and return true or false, depending on the result of your test To get the values of controls on the page, call the built-in GetControlValidationValue method passing the name of the control that you want. This code retrieves the value of the control whose name was set in the CityId property and returns false to indicate a failed test if the control is empty:

protected override bool EvaluateIsValid()
{
 string CityValue = this.GetControlValidationValue(this.CityId);
 if (CityValue == "")
 {
   return false;
 }
 return true;
}

In real life, you'd probably call validation methods built into your middle-tier business objects to check your data.

To test your Validator, just add a Web project to the Solution you created for your Validator control. Your new Validator will appear at the top of the Toolbox -- you can drag it onto the page, set your properties and debug your code. If you make a change to your Validator control, you'll have to rebuild your solution, delete the control from the page, and drag it back onto the page from the Toolbox.


About the Author

Peter Vogel is a principal in PH&V Information Services, specializing in ASP.NET development with expertise in SOA, XML, database, and user interface design. His most recent book ("rtfm*") is on writing effective user manuals, and his blog on technical writing can be found at rtfmphvis.blogspot.com.

Reader Comments:

Thu, Aug 13, 2009 Jon

Great article and excellent discussion on the pros and cons of these various tools that Microsoft provides to us. I'm one of those IT developers, working in a small group of a very large financial institution, where we have to be very quick and responsive for our users, so we very much use a RAD approach. I'm definitely not a junior developer, but I do embrace many of those tools (validators, ObjectDataSource, strongly-typed data sets) as a means to produce a high quality product quickly. But, I also strive to hold to the principles like n-tier design, encapsulation, and so on in a way that makes sense for our applications. Peter, thanks for the article!

Tue, Aug 11, 2009 Peter Vogel Canada

I certainly agree that it's hard to decide what validation should or shouldn't be done in the UI. A lot of decisions are made on viability rather than being guided by any principle. For instance, before Web Services and AJAX, any data validation that required database access was done at the server because it couldn't be done in the client (without embedding arrays of data in JavaScript code, at any rate). That hardly seems like a good basis for a methodology. I also agree that many of the tools that Microsoft has generated (I wouldn't say "most") have been created to support developing applications that don't require a full-time professional programmer working for months on end--and I think that's a good thing. All too often we take our "principles" and "guidelines" and "best practices" and turn them into rigid rules that must be followed by all people in all places, regardless of the context--and I think that's too bad.

Mon, Aug 10, 2009 Popa Dumitru-Stelian

Is really difficult to say what rule check should remain in UI and what rule check should be put in second or third layer. Let's imagine a scenario: User needs to input an email for password recovery. It really makes sense in first phase validate that the user entered a valid email - we do this validation in UI , and AFTER we validate that the email exists in the DB in the middle/third tier. Also if an option exists somewhere it does not means that you are forced to use it. My only problemm with this is a MSDN more detailed guidelines.

Thu, Aug 6, 2009 CyberTech

if possible please put the screen shot.

Thu, Aug 6, 2009 Trevor Goertzen

The reason MS has created tools that defy modern methodologies is to make things easy for junior developers. Remember, their goal is to get as many people using their technologies as possible. Experienced developers can ignore many of the tools included in .NET. I rarely even use ViewState.

Tue, Jul 28, 2009 Peter Vogel Canada

I think that the SqlDataSource is there to support people who want to build single-tier applications. And I think that's a good thing: Not every application needs an object model and middle-tier business developer. As for validator: as Evan points out, your user interface interacts with your business objects--it doesn't matter if that happens from an event triggered by a validator or an event triggered by the Page. Even then, I think that asking the user to go all the way back to the server and into the middle-tier in order to find out that they've entered the date in the wrong format is not the way to build to build scalable applications--the more validation that you can build into the UI (and, ideally, have execute in the client) the better experience the user will have and the more scalable the application will be. We tend to forget that these are principles and guidelines we follow--not the immutable rules of the universe.

Tue, Jul 21, 2009 Evan Barr www.ProjectInVision.com

Robert's comment is only partially right. Your validators should call middle-tier code (as mentioned in the article). The interface to the middle-tier should be robust enough so that it is unlikely to need changes later. You can then change your middle-tier code to your hearts desire without needing to change your validators.

Much of .Net is targeted at IT and not Software companies. Most coding projects in IT will only be successful if the coding is quick and dirty (also known as RAD). This is because they only have one company paying for the results. There is no point in arguing about the cost of supporting a badly coded product when the alternative is no product at all. .Net methodologies are mostly targeted at RAD.

It is critical that the rest of us figure out which of the .Net methodologies must be ignored or at least make sure that our implementation is tweaked to meet best practices.

Fri, Jul 17, 2009 Robert

I don't get it. The software industry, including Microsoft, spent the last decade or more convincing us to use n-tier architectures, and to never, EVER put business rules into the UI, but to separate that out.

Now we have validators in every page, which means if a business rule changes, we've got them distributed everywhere for a maintenance nightmare.

Same thing for data sources. "Separate your data from your UI" has been preached just as long. And then here come the SqlDataSource control to put in your UI, and the same maintenance nightmare issues come back like zombies in a Stephen King novel.

And just because MS decides to revert back to old, flawed methodologies, or give us the tools to do so, industry experts should not be encouraging us to follow them.

Can we have some consistency and common sense for a while, please?

Add Your Comments Now:

Your Name:(optional)
Your Email:(optional)
Your Location:(optional)
Comment:
Please type the letters/numbers you see above