Browse DevX
Sign up for e-mail newsletters from DevX


New Features in Enterprise Library 3.0: Validation Block  : Page 2

Avoid the tedious and error-prone task of writing validation "plumbing" code by integrating the Validation Application Block into your .NET applications.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Simple Example Walkthrough
In this example, you will see how to use built-in validators to validate an object named Employee. To begin, create a new Visual C# Windows Forms application named ValidationExample. In the new project, add references to the Validation Block assemblies. Then add a new class named Employee to the project that contains the code in Listing 1.

Note that the Employee class properties in Listing 1 are decorated with built-in validator classes such as RangeValidator, StringLengthValidator, NotNullValidator, etc., and that the constructors of each validator accept the MessageTemplate property as a named parameter. The MessageTemplate property lets you specify the validation message that will be displayed to the user if validation fails.

After decorating the Employee class with all the validation related attributes, the next step is to execute those validation rules from a client application. For this purpose, add a button named btnValidateEmployee to the Windows form and modify its Click event to look as follows:

private void btnValidateEmployee_Click(object sender, EventArgs e) { Employee emp = new Employee(); emp.EmployeeID = 100001; emp.Name = "Dave Campell"; emp.Gender = "Male"; emp.BirthDate = DateTime.Now.AddYears(-130); emp.EmailAddress = "test@test.com"; lstValidationResults.Items.Clear(); //Validate the Employee object ValidationResults results = Validation.Validate(emp); //Inspect the ValidationResults object if (!results.IsValid) { //If not valid, loop through the ValidationResults foreach (ValidationResult result in results) { lstValidationResults.Items.Add("Key = " + result.Key); lstValidationResults.Items.Add("Message = " + result.Message); lstValidationResults.Items.Add("....."); } } }

The preceding code creates an instance of the Employee class and sets its properties to appropriate values. Specifically it intentionally sets the EmployeeID and BirthDate properties to values that violate the validation rules supplied at the time of Employee class declaration.

Then it invokes the Validation.Validate() method, passing in the Employee object as an argument, and captures the return value (of type ValidationResults collection) in a local variable:

ValidationResults results = Validation.Validate(emp);

Figure 1. Validation Output: The EmployeeID and BirthDate properties are decorated with RangeValidator and RelativeDateTimeValidator classes that result in the validation message being displayed in the ListBox.
When the Validate method returns, the results variable contains a collection of ValidationResult objects. In the foreach loop at the end of the method, the code iterates through the returned collection to display the Key and Message values of each of the ValidationResult objects in a ListBox. Figure 1 shows the output in the downloadable sample application.

The previous example used Validation.Validate() to trigger the validation, but alternatively, you can create an Employee validator class using the ValidationFactory.CreateValidator() method and then invoke its Validate() method to get the same result:

Validator<Employee> empValidator = ValidationFactory.CreateValidator <Employee>(); ValidationResults results = empValidator.Validate(emp);

ValidationResult object
As shown in the preceding section, the object returned from the Validation.Validate() method is a collection object of type ValidationResults that is made up of ValidationResult objects. By checking the ValidationResults.IsValid property, you can check for any validation errors generated during the validation process. If the IsValid property returns false, you can then loop through the ValidationResults collection to examine each of the ValidationResult objects contained in the collection. The ValidationResult object exposes the properties shown in Table 2:

Table 2: The table lists the exposed ValidationResult class properties and provides a brief description of each.
Property Description
Key Contains the name of the member that is associated with the validator.
Message Describes the validation failure.
Tag Provides the value supplied by the user and is mainly used for categorizing the generated validation messages.
Validator Returns reference to the validator that performed the validation.

Grouping Validations with Rulesets
Although the single-validation-per-property approach shown so far in this article with the Employee class works fine, there are times where you might want to have a finer level of control over the validation rules used in different situations. For example, you might want to apply one set of validation rules to an Employee instance before persisting its data in a database, but apply a different set of validation rules tailored toward user interface processing. You can use rulesets to accomplish that. A ruleset is a mechanism through which you can evaluate a set of related validation rules as a named group.

In this case, you can create two different rulesets named "DatabaseRuleset" and "UserInterfaceRuleset," and invoke whichever is appropriate at runtime by supplying the name of the ruleset to the Validate() method. If you don't specify a ruleset as part of the type declaration, the Validation Block uses a default "anonymous" ruleset. Here are the steps to implement rulesets in your application:

  1. Specify the Ruleset attribute as one of the named parameters when you declare the validator attribute. If you are using a configuration file to specify the validation behavior, set the name attribute of the element to the appropriate value.
  2. Supply the name of the desired ruleset as an argument to the Validate() method.
  3. Process the ValidationResults collection returned from the Validate() method to examine the messages generated during validation.
To illustrate, modify the EmployeeID and Name properties of the Employee class to add a ruleset named "DatabaseRuleset" (for brevity, the following code shows only the modified lines):

public class Employee { ----- ----- [RangeValidator(1,RangeBoundaryType.Inclusive,10000, RangeBoundaryType.Inclusive,MessageTemplate="Employee ID must be within 1 to 10000", Ruleset="DatabaseRuleset")] public int EmployeeID { get { return employeeID; } set { employeeID = value; } } [StringLengthValidator(50,MessageTemplate="Employee Name must be within 50 characters", Ruleset="DatabaseRuleset")] public string Name { get { return name; } set { name = value; } } ---- ----- }

Note how the preceding code uses the named parameter Ruleset (set to "DatabaseRuleset" in the preceding code) to specify the name of the ruleset. After modifying the class, the next step is to trigger the validation using the ruleset as an argument.

Add a button named btnValidateEmployeeWithDatabaseRuleset to the form and modify its Click event as follows:

private void btnValidateEmployeeWithDatabaseRuleset_Click (object sender, EventArgs e) { Employee emp = new Employee(); emp.EmployeeID = 100001; emp.Name = "Dave Campell"; emp.Gender = "Male"; emp.BirthDate = DateTime.Now.AddYears(-130); emp.EmailAddress = "test@test.com"; // Validate the Employee object ValidationResults results = Validation.Validate(emp, "DatabaseRuleset"); // Inspect the ValidationResults object if (!results.IsValid) { lstValidationResults.Items.Clear(); // If not valid, loop through // the ValidationResults foreach (ValidationResult result in results) { lstValidationResults.Items.Add( "Key = " + result.Key); lstValidationResults.Items.Add( "Message = " + result.Message); lstValidationResults.Items.Add( "....."); } } }

Note that when the listing invokes the Validate() method it passes the name of the ruleset as an argument:

ValidationResults results = Validation.Validate( emp, "DatabaseRuleset");

Because of the ruleset parameter, the Validate() method executes only the validation rules associated with the EmployeeID and Name properties. The application displays the resulting output in the list box.

At this point, it's worth noting that you can have different attributes with different validations grouped within different rulesets on a single property, so you can arrange validation groups however you like. In addition, you can attach multiple validation rules attached to any property, letting you validate the value in multiple ways. And finally, there's no restriction that prevents you from using any combination of attribute-based programmatic, or configuration-based validation. As you can see, the Validation Block gives you the freedom to adapt to whatever validation combination or technique is most useful.

Thanks for your registration, follow us on our social networks to keep up-to-date