How to Use the Microsoft Enterprise Library Validation Application Block, Part 1

All user input is evil, and you know it. Since the inception of .NET, ASP.NET developers have had access to the ASP.NET Validators Control Library, which made the previously tedious process of validating form input simple and in many instances, trivial. Microsoft's Enterprise Library makes this familiar ASP.NET functionality available at the object level in your applications via the Validation Application Block, which I've been using throughout some of my new projects.

It can take a while to get familiar with the Validation Application Block, so my goal here is to show you how to quickly get started with it using attribute-based validation, which in my opinion is the simplest way to implement validation. By the time you're doing reading this you'll know how to use built-in validators such as the RangeValidator, RegexValidator, DateTimeRangeValidator, and so forth.

Introduction to the Validation Application Block Built-in Validators

What can the Validation Application Block do, exactly? Well, here's a list of the validators that are built-in to the Validation Application Block:

In addition to these built-in validators the Validation Application Block also includes methods for creating user-defined validators and for composing validators into ValidatorCompositions which can process more complex validation rules.

How to Add the Validation Application Block to a Visual Studio Project

Before you worry about how to start adding validators to all of your business objects, you need to include the necessary assemblies into your Visual Studio / Visual [X] Express projects. After you've downloaded and installed the Enterprise Library 5.0 or *Enterprise Library 4.1 binaries onto your system, open your existing Visual Studio Project or create a new one. Open the Solution Explorer, expand the References folder, right click on the References folder and click on Add Reference

Select the following two assemblies (typically they'll be installed to your system's GAC so you won't need to go hunting for them) - Enterprise Library Shared Library and Enterprise Library Validation Application Block. The Validation Application Block depends on Shared Library (as do many other components in the Enterprise Library), and you'll run into some run-time errors without it included in your project's References folder.

If you're designing a WinForms or an ASP.NET application, you may want to include the special Validation Application Block WinForms Integration or Validation Application Block ASP.NET Integration assemblies, but if you're designing validation rules for individual business object classes and not presentation-layer events, you may not need them.

Example: Using Built-in Validators for Validating an Address

I'm going to end this post with a simple example which will show you how to get started using the Validation Application Block's attribute-based validators, and I'll expand on this in subsequent posts. We're going to work with a simple class which contains an address based in the United States:

public class USAddress
{
    public string RecipientName { get; set; }
    public string Street { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string ZipCode { get; set; }
}

We know that addresses based in the United States need to comply with the following business rules:

  1. All of these fields must be filled in;
  2. A street must contain a street name and a street number;
  3. A state code must be two characters in length; and
  4. A zip code contains exactly five or nine digits.

 So, let's examine how we can use some validators to ensure that this business object enforces these business rules. The first step is to ensure that our source code references the correct namespace:

using Microsoft.Practices.EnterpriseLibrary.Validation.Validators;

 Next, let's go ahead and enforce business rule #1 - all address fields must be filled in. We can accomplish by decorating each field with NotNullValidator attribute:

using System;
using System.Text;
using Microsoft.Practices.EnterpriseLibrary.Validation.Validators;

namespace Business_Entities
{
    public class USAddress
    {
        [NotNullValidator()]
        public string RecipientName { get; set; }

        [NotNullValidator()]
        public string Street { get; set; }

        [NotNullValidator()]
        public string City { get; set; }

        [NotNullValidator()]
        public string State { get; set; }

        [NotNullValidator()]
        public string ZipCode { get; set; }
    }
}

Let's see if this works. Here's some simple code we can use to test the validators by calling the Validator.Validate() method against an instance of this class.

using System;
using System.Text;
using Business_Entities;
using Microsoft.Practices.EnterpriseLibrary.Validation;

namespace Basic_Validation__Console_
{
    class Program
    {
        static void Main(string[] args)
        {
            //Create a blank test address
            USAddress testaddress = new USAddress();

            //Create a new validator using the ValidationFactory method
            Validator validator = ValidationFactory.CreateValidator<USAddress>();
            ValidationResults results = new ValidationResults();
            validator.Validate(testaddress, results);

            Console.Write("Is the test address valid? {0}", results.IsValid);
            //Stop the console screen from disappearing immediately.
            Console.ReadKey(); 
        }
    }
}

And what happens when we run this test code? 

Smells like success to me. Let's re-run this test using a valid address.

//A real(ish) test address
USAddress testaddress = new USAddress();
testaddress.RecipientName = "Bob Jones";
testaddress.City = "Beverly Hills";
testaddress.State = "CA";
testaddress.Street = "1205 Rodeo Drive";
testaddress.ZipCode = "90210";

And the result is: 

Looks like the NotNullValidator is working as intended. But wait a minute, how did this ValidationFactory.CreateValidator() method know how to create a Validator object that properly validates any instance of a USAddress object?

Because we decorated the USAddress class with one or more Validator attributes, the underlying Validation Application Block library automatically implements and registers a Validator class designed to support the USAddress class. Internally, the Validation Application Block uses an instance of Unity to resolve a custom validator for the USAddress class on-the-fly.

Let's enforce some of the other business rules, starting with the state code.

[NotNullValidator()]
[StringLengthValidator(2, RangeBoundaryType.Inclusive, 2, RangeBoundaryType.Inclusive)]
public string State { get; set; }

As you can see I've added a StringLengthValidator in addition to the NotNullValidator that was already in place (yes, you can add more than one Validator attribute to a field.) I've specified the following parameters for this validator:

  1. lowerBound = 2
  2. lowerBound RangeBoundaryType = Inclusive (meaning that this value is included in the range of acceptable string length values)
  3. upperBound = 2
  4. upperBound RangeBoundaryType = Inclusive (this value is also included in the range of acceptable string length values)

There are three possible range boundary types:

  1. Inclusive, which is the equivalent of [] in traditional mathematical syntax;
  2. Exclusive, which is the equivalent of () in traditional mathematical syntax; and
  3. Ignore, which is the equivalent of (infinity, or infinity) in traditional mathematical syntax.

Now the next change we need to make is to check for a valid zip code, which can be either 9 or 5 digits. I'm going to do this using a RegexValidator - another way to do this is to create an ValidatorComposition (an "Or" type as opposed to an "And" type) with two different string length validators. Here's what our RegexValidator looks like:

[NotNullValidator()]
[RegexValidator(@"^(\d{5}-\d{4}|\d{5}|\d{9})$|^([a-zA-Z]\d[a-zA-Z] \d[a-zA-Z]\d)$")]
public string ZipCode { get; set; }

Hat tip to Microsoft's Patterns & Practices group for providing me with the regular expression for validating US zip codes.

Now, our source code for testing this validation has not changed one bit - all of the changes to the validator for the USAddress class occur behind the scenes. Once I recompile my class library and re-run the test I should get a "validation successful" message back from the console: 

Well hell yeah, that'll do it! If I wanted to validate the last business rule (the street address must contain both a street name and number,) I could write another RegexValidator for that and hook it up in much the same way as my RegexValidator for zip codes. And that's all it really takes to get started with the Microsoft Enterprise Library Validation Application Block. In my next article on the subject I'll include some examples on how / when you should use ObjectValidators and why they're so useful.

*Although the latest version of the Validation Application Block is version 5.0, my example code uses Enterprise Library version 4.1, namely because my individual development environment has some issues with the Validation Application Block 5.0 and the GAC. Given that there are no major syntactical differences between the two versions, I'm going to do what any economical programmer would do and use what works instead of dicking around with configuration files, assembly directories, and things that are frankly tangential to developing applications.

Discussion, links, and tweets

I'm the CTO and founder of Petabridge, where I'm making distributed programming for .NET developers easy by working on Akka.NET, Phobos, and more..