Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

Microsoft Enterprise Library 5.0 - Introduction to Validation Block

4.62/5 (17 votes)
18 Sep 2011CPOL6 min read 89.4K   7.8K  
Introduces common tasks with examples to the validation block in Microsoft Enterprise Library 5.0

Introduction

The Validation block in Microsoft Enterprise Library 5.0 is used to define validation rules and manage them easily in different ways across applications.

It includes a comprehensive number of built-in validators including null validation, range validation, self validation, etc. It also provides a superior way to validate the objects against predefined rules and provides the results with valuable information.

In addition to common validation mechanism, it supports technology specific validation for WPF, WCF and ASP.NET.

In this article, I will focus on the common tasks in validation block and try to explain them with examples. I developed a demo application for testing validations and you find the examples in it and find out how it works. The examples are taken from the demo project and developed using Microsoft Visual Studio 2010, .NET Framework 4.0, and Microsoft Enterprise Library 5.0.

You can obtain Microsoft Enterprise Library assembly files and other relevant resources from the following address:

Basics

There are 3 types of validators in validation block:

  1. Value validators
  2. Composite validators
  3. Object validators

Value validators: Perform specific validations such as validating the length of string, checking if the value is null or not, and validating the number against a predefined range.

Composite validators: Allow to combine with other validators to create a complex set of validations. Two types of composite validations exist: AND validator and OR validator. By using these composite validators with other validators, it is possible to define the validation logic between the validators.

Object validators: Perform all validations defined for the type and supports the validation against the objects in collections.

Preparation

To use the validation block, you must reference the required assemblies. The main validation block assembly is Microsoft.Practices.EnterpriseLibrary.Validation.dll.

If you intend to use the integration features for ASP.NET, Windows Forms, WPF or WCF, you must also reference the relevant assembly from the list below that contains these features:

  • For ASP.NET, Microsoft.Practices.EnterpriseLibrary.Validation.Integration.AspNet.dll
  • For Windows Forms, Microsoft.Practices.EnterpriseLibrary.Validation.Integration.WinForms.dll
  • For WPF, Microsoft.Practices.EnterpriseLibrary.Validation.Integration.WPF.dll
  • For WCF, Microsoft.Practices.EnterpriseLibrary.Validation.Integration.WCF.dll

How to Use Validation Block

Firstly, you must initialize a validator instance which you use to create and execute validations through the following lines:

C#
ValidatorFactory valFactory = 
	EnterpriseLibraryContainer.Current.GetInstance<ValidatorFactory>();

In the lines above, the Unity dependency injection mechanism is used to create the objects related with validations. However, it is possible to use another Dependency Injection mechanism for different purposes if you prefer through an implementation of the IServiceLocator interface.

Let’s create our customer to be used for validation:

C#
public class AttributeCustomer 
{
    [NotNullValidator(MessageTemplate = "Customer must have valid no")]
    [StringLengthValidator(5, RangeBoundaryType.Inclusive, 
		5, RangeBoundaryType.Inclusive, 
		MessageTemplate = "Customer no must have {3} characters.")]
    [RegexValidator("[A-Z]{2}[0-9]{3}", 
	MessageTemplate = "Customer no must be 2 capital letters and 3 numbers.")]
    public string CustomerNo { get; set; }
}

Then, we create a required validator depending on our validation preference. In this context, we prefer validation block attributes approach.

C#
Validator<AttributeCustomer> cusValidator = 
			valFactory.CreateValidator<AttributeCustomer>();

We initialize our customer object which requires validations and validate it through the attributes defined in the customer object type.

C#
var customer = new AttributeCustomer();
customer.CustomerNo = "AB123";
customer.FirstName = "Brown";
customer.LastName = "Green";
customer.BirthDate = "1980-01-01";
customer.CustomerType = "VIP";

ValidationResults valResults = cusValidator.Validate(customer);

Lastly, we have validations results and we can check if the object is valid. If it is not valid, we can find the reasons why the validation fails and the failure sources (object property in this context).

C#
if (valResults.IsValid)
{
    MessageBox.Show("Customer information is valid");
}
else
{
    foreach (ValidationResult item in valResults)
    {
        // Put your validation detection logic
    }
}

Approaches

There are five validation approaches which you can prefer during validations. Each one has advantages and disadvantages over each other, but I do not focus on these details now. Also, it is possible to apply multiple approaches at the same time. For example, you can implement self validation and data annotation attributes approaches at the same time, which gives you much flexibility.

  1. Rule sets in configuration
  2. Validation block attributes
  3. Data annotation attributes
  4. Self-validation
  5. Validators created programmatically

Rule sets in Configuration

In this approach, we put our validation rules into the configuration file (web.config in ASP.NET and app.config in Windows applications). Here is an example showing how to define validation rules:

XML
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="validation" type="Microsoft.Practices.EnterpriseLibrary.
	Validation.Configuration.ValidationSettings, 
	Microsoft.Practices.EnterpriseLibrary.Validation, Version=5.0.414.0, 
	Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
  </configSections>
  <validation>
    <type name="ELValidation.Entities.BasicCustomer" 
		defaultRuleset="BasicCustomerValidationRules"
      assemblyName="ELValidation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
      <ruleset name="BasicCustomerValidationRules">
        <properties>
          <property name="CustomerNo">
            <validator type="Microsoft.Practices.EnterpriseLibrary.
		Validation.Validators.NotNullValidator, 
		Microsoft.Practices.EnterpriseLibrary.Validation"
              negated="false" messageTemplate="Customer must have valid no"
              tag="CustomerNo" name="Not Null Validator" />
            <validator type="Microsoft.Practices.EnterpriseLibrary.
		Validation.Validators.StringLengthValidator, 
		Microsoft.Practices.EnterpriseLibrary.Validation"
              upperBound="5" lowerBound="5" lowerBoundType="Inclusive" 
		upperBoundType="Inclusive"
              negated="false" messageTemplate="Customer no must have {3} characters."
              tag="CustomerNo" name="String Length Validator" />
            <validator type="Microsoft.Practices.EnterpriseLibrary.
		Validation.Validators.RegexValidator, 
		Microsoft.Practices.EnterpriseLibrary.Validation"
              pattern="[A-Z]{2}[0-9]{3}" options="None" patternResourceName=""
              patternResourceType="" 
		messageTemplate="Customer no must be 2 capital letters and 3 numbers."
              messageTemplateResourceName="" messageTemplateResourceType=""
              tag="CustomerNo" name="Regex Validator" />
          </property>
        </properties>
      </ruleset>
    </type>
  </validation>
</configuration>

In our configuration file, we first define a config section for Enterprise Library validation settings. Then, we define our validation rules as shown in the example. First, define the type to which rules are applied through “type” tag and define each property for the type and relevant validations for the property.

We can write our validation rules manually or do it through Enterprise Library Configuration tool which is most probably located in the following path:

Program Files Folder\Microsoft Enterprise Library 5.0\Bin\EntLibConfig.NET4.exe

This tool helps you much and prevents you from the complexities during configuration because it can be hard to do it manually.

In this example, we define a ruleset name, BasicCustomerValidationRules, which is used to validate our object against specific rules as shown in the following lines:

C#
public class BasicCustomer : ICustomer
{
    public string CustomerNo { get; set; }
    public string FirstName { get; set; }
    public string MiddleName { get; set; }
    public string LastName { get; set; }
    public string BirthDate { get; set; }
    public string CustomerType { get; set; }
}

Validator<BasicCustomer> cusValidator = 
	valFactory.CreateValidator<BasicCustomer>("BasicCustomerValidationRules");
ValidationResults valResults = cusValidator.Validate(customer);

We test the customer object if the value of the customerno is not null, it has exactly 5 characters, and it has a similar format like AB123.

Validation Block Attributes

In this approach, we define our validations through the attributes defined in Enterprise Library validation block.

C#
[NotNullValidator(MessageTemplate = "Customer must have valid no")]
[StringLengthValidator(5, RangeBoundaryType.Inclusive, 
		5, RangeBoundaryType.Inclusive, 
		MessageTemplate = "Customer no must have {3} characters.")]
[RegexValidator("[A-Z]{2}[0-9]{3}", 
	MessageTemplate = "Customer no must be 2 capital letters and 3 numbers.")]
public string CustomerNo { get; set; }

In this example, we check if the customerno is not null, it has exactly 5 characters, and it has a similar format like AB123.

Also, message template is a good way to provide meaningful messages on failure with the flexibility to be replaced by Enterprise Library validation block for brackets.

In this example, if the number of characters in CustomerNo is different from 5, we get the error message like Customer no must have 5 characters.

Data Annotation Attributes

In this approach, we define our validations through the attributes defined within System.ComponentModel.DataAnnotations assembly.

In the following example, we define 3 validation rules for CustomerNo property, so that it cannot be null, it must have exactly 5 characters, and the format of the CustomerNo should be like this AB123.

C#
[Required(ErrorMessage = "Customer no can not be empty")]
[StringLength(5, ErrorMessage = "Customer no must be 5 characters.")]
[RegularExpression("[A-Z]{2}[0-9]{3}", 
	ErrorMessage = "Customer no must be 2 capital letters and 3 numbers.")]
public string CustomerNo { get; set; }

This approach is widely used in conjunction with Entity Framework and ASP.NET validations.

Self-validation

This approach gives much flexibility to us in order to create and execute complex validation rules.

In order to implement this approach, we first decorate HasSelfValidation attribute with the object type as shown in the following example:

C#
[HasSelfValidation]
public class AttributeCustomer
{
    …
}

Then, we write our validation logic by putting SelfValidation attribute on the top of the method which executes the validations.

C#
[SelfValidation]
public void Validate(ValidationResults validationResults)
{
    var age = DateTime.Now.Year - DateTime.Parse(BirthDate).Year;

    // Due to laws, only customers older than 18 can be registered 
    // to system and allowed to order products
    if (age < 18)
    {
        validationResults.AddResult(
            new ValidationResult("Customer must be older than 18",
                this,
                "BirthDate",
                null,
                null));
    }
}

In this example, we check BirthDate property value if the customer is bigger than 18 or not, then append the validation results to validation result collection on failure.

Validators Created Programmatically

This approach is different from the others because validation rules are created programmatically and executed independent of the type.

First, we define our validation rules:

C#
Validator[] validators = new Validator[] 
{ 
    new NotNullValidator(false, "Value can not be NULL."),
    new StringLengthValidator(5, RangeBoundaryType.Inclusive, 
	5, RangeBoundaryType.Inclusive,  "Value must be between {3} and {5} chars.")
};

Then, we add them into one of the composite validators depending on your preference.

C#
var validator = new AndCompositeValidator(validators);

Lastly, we execute the validation rules against our object to be tested and get the results.

C#
ValidationResults valResults = validator.Validate("Value to be tested…");

In this example, we check Value to be tested… if it is not null and it has five exact characters.

Finally, I want to mention about the validations against collections. Actually, it is similar to the validations for objects.

C#
// Initialize our object and set the values
var customer = new AttributeCustomer();
            
FillCustomerInfo(customer);

// Create a list of objects and add the objects to be tested to the list
List<AttributeCustomer> customers = new List<AttributeCustomer>();
customers.Add(customer);

// Initialize our validator by providing the type of objects in the list and validate them
Validator cusValidator = new ObjectCollectionValidator(typeof(AttributeCustomer));
ValidationResults valResults = cusValidator.Validate(customers);

// Show our validation results
ShowResults(valResults);

Final Words

The validation block is very powerful and saves much time really. Also, it is easy to implement and maintain the validations. Of course, the validation block is larger than what I try to illustrate in this article, but I expect that you will understand how it works and start to use in your applications. Lastly, Microsoft Enterprise Library 5.0 has integration features for ASP.NET, Winforms, WPF, and WCF. I will focus on these integration features in my next articles.

History

  • 18th September, 2011: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)