programming4us
programming4us
ENTERPRISE

Microsoft Enterprise Library : Banishing Validation Complication - What Does the Validation Block Do? (part 2)

- How To Install Windows Server 2012 On VirtualBox
- How To Bypass Torrent Connection Blocking By Your ISP
- How To Install Actual Facebook App On Kindle Fire
11/15/2013 6:49:17 PM
2.2 Validating with Attributes

If you have full access to the source code of your application, you can use attributes within your classes to define your validation rules. You can apply validation attributes in the following ways:

  • To a field. The Validation block will check that the field value satisfies all validation rules defined in validators applied to the field.

  • To a property. The Validation block will check that the value of the get property satisfies all validation rules defined in validators applied to the property.

  • To a method that takes no parameters. The Validation block will check that the return value of the method satisfies all validation rules defined in validators applied to the method.

  • To an entire class, using only the NotNullValidator, ObjectCollection Validator, AndCompositeValidator, and OrCompositeValidator). The Validation block can check if the object is null, that it is a member of the specified collection, and that any validation rules defined within it are satisfied.

  • To a parameter in a WCF Service Contract. The Validation block will check that the parameter value satisfies all validation rules defined in validators applied to the parameter.

  • To parameters of methods that are intercepted, by using the validation call handler in conjunction with the Policy Injection application block.

Each of the validators described in the previous section has a related attribute that you apply in your code, specifying the values for validation (such as the range or comparison value) as parameters to the attribute. For example, you can validate a property that must have a value between 0 and 10 inclusive by applying the following attribute to the property definition, as seen in the following code.

[RangeValidator(0, RangeBoundaryType.Inclusive, 10, RangeBoundaryType.Inclusive)]

DataAnnotations Attributes

In addition to using the built-in validation attributes, the Validation block will perform validation defined in the vast majority of the validation attributes in the System.ComponentModel.DataAnnotations namespace. These attributes are typically used by frameworks and object/relational mapping (O/RM) solutions that auto-generate classes that represent data items. They are also generated by the ASP.NET validation controls that perform both client-side and server-side validation. While the set of validation attributes provided by the Validation block does not map exactly to those in the DataAnnotations namespace, the most common types of validation are supported. A typical use of data annotations is shown here.

[System.ComponentModel.DataAnnotations.Required(
ErrorMessage = "You must specify a value for the product ID.")]
[System.ComponentModel.DataAnnotations.StringLength(6,
ErrorMessage = "Product ID must be 6 characters.")]
[System.ComponentModel.DataAnnotations.RegularExpression("[A-Z]{2}[0-9]{4}",
ErrorMessage = "Product ID must be 2 capital letters and 4 numbers.")]
public string ID { get; set; }

In reality, the Validation block validation attributes are data annotation attributes, and can be used (with some limitations) whenever you can use data annotations attributes—for example, with ASP.NET Dynamic Data applications. The main difference is that the Validation block attribute validation occurs only on the server, and not on the client.

Also keep in mind that, while DataAnnotations supports most of the Validation block attributes, not all of the validation attributes provided with the Validation block are supported by the built-in .NET validation mechanism. For more information, see the documentation installed with Enterprise Library, and the topic "System.Component Model.DataAnnotations Namespace" at http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.aspx.

2.3 Self-Validation

Self-validation might sound as though you should be congratulating yourself on your attractiveness and wisdom, and your status as fine and upstanding citizen. However, in Enterprise Library terms, self-validation is concerned with the use of classes that contain their own validation logic.

For example, a class that stores spare parts for aircraft might contain a function that checks if the part ID matches a specific format containing letters and numbers. You add the HasSelfValidation attribute to the class, add the SelfValidation attribute to any validation functions it contains, and optionally add attributes for the built-in Validation block validators to any relevant properties. Then you can validate an instance of the class using the Validation block. The block will execute the self-validation method.

Note

Self-validation cannot be used with the UI validation integration features for Windows Forms, WPF, or ASP.NET.

Self-validation is typically used where the validation rule you want to apply involves values from different parts of your class or values that are not publicly exposed by the class, or when the validation scenario requires complex rules that even a combination of composed validators cannot achieve. For example, you may want to check if the sum of the number of products on order and the number already in stock is less than a certain value before allowing a user to order more.

[HasSelfValidation]
public class AnnotatedProduct : IProduct
...
... code to implement constructor and properties goes here
...
[SelfValidation]
public void Validate(ValidationResults results)
{
string msg = string.Empty;
if (InStock + OnOrder > 100)
{
msg = "Total inventory (in stock and on order) cannot exceed 100 items.";
results.AddResult(new ValidationResult(msg, this, "ProductSelfValidation",
"", null));
}
}

The Validation block calls the self-validation method when you validate this class instance, passing to it a reference to the collection of ValidationResults that it is populating with any validation errors found. The code above simply adds one or more new Validation Result instances to the collection if the self-validation method detects an invalid condition. The parameters of the ValidationResult constructor are:

  • The validation error message to display to the user or write to a log. The ValidationResult class exposes this as the Message property.

  • A reference to the class instance where the validation error was discovered (usually the current instance). The ValidationResult class exposes this as the Target property.

  • A string value that describes the location of the error (usually the name of the class member, or some other value that helps locate the error). The ValidationResult class exposes this as the Key property.

  • An optional string tag value that can be used to categorize or filter the results. The ValidationResult class exposes this as the Tag property.

  • A reference to the validator that performed the validation. This is not used in self-validation, though it will be populated by other validators that validate individual members of the type. The ValidationResult class exposes this as the Validator property.

2.4 Validation Rule Sets

A validation rule set is a combination of all the rules with the same name, which may be located in a configuration file or other configuration source, in attributes defined within the target type, and implemented through self-validation. In other words, a rule set includes any type of validation rule that has a specified name.

Note

Rule set names are case-sensitive. The two rule sets named MyRuleset and MyRuleSet are different!

How do you apply a name to a validation rule? And what happens if you don't specify a name? In fact, the way it works is relatively simple, even though it may appear complicated when you look at configuration and attributes, and take into account how these are actually processed.

To start with, every validation rule is a member of some rule set. If you do not specify a name, that rule is a member of the default rule set; effectively, this is the rule set whose name is an empty string. When you do specify a name for a rule, it becomes part of the rule set with that name.

Assigning Validation Rules to Rule Sets

You specify rule set names in a variety of ways, depending on the location and type of the rule:

  • In configuration. You define a type that you want to apply rules to, and then define one or more rule sets for that type. To each rule set you add the required combination of validators, each one representing a validation rule within that rule set. You can specify one rule set for each type as the default rule set for that type. The rules within this rule set are then treated as members of the default (unnamed) rule set, as well as that named rule set.

  • In Validation block validator attributes applied to classes and their members. Every validation attribute will accept a rule set name as a parameter. For example, you specify that a NotNullValidator is a member of a rule set named MyRuleset, like this.

    [NotNullValidator(MessageTemplate = "Cannot be null",
    Ruleset = "MyRulesetName")]
  • In SelfValidation attributes within a class. You add the Ruleset parameter to the attribute to indicate which rule set this self-validation rule belongs to. You can define multiple self-validation methods in a class, and add them to different rule sets if required.

[SelfValidation(Ruleset = "MyRulesetName")]

Configuring Validation Block Rule Sets

The Enterprise Library configuration console makes it easy to define rule sets for specific types that you will validate. Each rule set specifies a type to which you will apply the rule set, and allows you to specify a set of validation rules. You can then apply these rules as a complete set to an instance of an object of the defined type.

The configuration for the examples

Figure 2. The configuration for the examples

Figure 2 shows the configuration console with the configuration used in the example application. It defines a rule set named MyRuleset for the validated type (the Product class). MyRuleset is configured as the default rule set, and contains a series of validators for all of the properties of the Product type. These validators include two Or Composite Validators (which contain other validators) for the DateDue and Description properties, three validators that will be combined with the And operation for the ID property, and individual validators for the remaining properties.

Note

When you highlight a rule, member, or validator in the configuration console, it shows connection lines between the configured items to help you see the relationships between them.

Specifying Rule Sets When Validating

You can specify a rule set name when you create a type validator that will validate an instance of a type. If you use the ValidatorFactory facade to create a type validator for a type, you can specify a rule set name as a parameter of the CreateValidator method. If you create an Object Validator or an Object Collection Validator programmatically by calling the constructor, you can specify a rule set name as a parameter of the constructor. Finally, if you resolve a validator for a type through the Enterprise Library Container, you can specify a rule set name as the string key value.

  • If you specify a rule set name when you create a validator for an object, the Validation block will apply only those validation rules that are part of the specified rule set. It will, by default, apply all rules with the specified name that it can find in configuration, attributes, and self-validation.

  • If you do not specify a rule set name when you create a validator for an object, the Validation block will, by default, apply all rules that have no name (effectively, rules with an empty string as the name) that it can find in configuration, attributes, and self-validation. If you have specified one rule set in configuration as the default rule set for the type you are validating (by setting the DefaultRule property for that type to the rule set name), rules within this rule set are also treated as being members of the default (unnamed) rule set.

The one time that this default mechanism changes is if you create a validator for a type using a facade other than ValidatorFactory. You can use the ConfigurationValidatorFactory, AttributeValidatorFactory, or Validation AttributeValidatorFactory to generate type validators. In this case, the validator will only apply rules that have the specified name and exist in the specified location.

For example, when you use a ConfigurationValidatorFactory and specify the name MyRuleset as the rule set name when you call the CreateValidator method, the validator you obtain will only process rules it finds in configuration that are defined within a rule set named MyRuleset for the target object type. If you use an AttributeValidator Factory, the validator will only apply Validation block rules located in attributes and self-validation methods of the target class that have the name MyRuleset.

Note

Configuring multiple rule sets for the same type is useful when the type you need to validate is a primitive type such as a String. A single application may have dozens of different rule sets that all target String.

Other  
  •  Microsoft Enterprise Library : A Cache Advance for Your Applications - How Do I Use the Caching Block (part 4) - Refreshing the Cache, Loading the Cache
  •  Microsoft Enterprise Library : A Cache Advance for Your Applications - How Do I Use the Caching Block (part 3) - Removing Items from and Flushing the Cache
  •  Microsoft Enterprise Library : A Cache Advance for Your Applications - How Do I Use the Caching Block (part 2)
  •  Microsoft Enterprise Library : A Cache Advance for Your Applications - How Do I Use the Caching Block (part 1) - Adding Items to and Retrieving Items from the Cache
  •  Microsoft Enterprise Library : A Cache Advance for Your Applications - How Do I Configure the Caching Block?
  •  Microsoft Visual Studio 2010 : Data Parallelism - Unrolling Sequential Loops into Parallel Tasks (part 4) - Handling Exceptions
  •  Microsoft Visual Studio 2010 : Data Parallelism - Unrolling Sequential Loops into Parallel Tasks (part 3) - Interrupting a Loop
  •  Microsoft Visual Studio 2010 : Data Parallelism - Unrolling Sequential Loops into Parallel Tasks (part 2) - The Parallel For Loop
  •  Microsoft Visual Studio 2010 : Data Parallelism - Unrolling Sequential Loops into Parallel Tasks (part 1)
  •  Programming Windows Services with Microsoft Visual Basic 2008 : Implementing the Worker Class, Creating the FileWorkerOptions Class
  •  
    Top 10
    - Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
    - Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
    - Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
    - Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
    - Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
    - Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
    - Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
    - Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
    - Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
    - Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
    REVIEW
    - First look: Apple Watch

    - 3 Tips for Maintaining Your Cell Phone Battery (part 1)

    - 3 Tips for Maintaining Your Cell Phone Battery (part 2)
    programming4us programming4us
    programming4us
     
     
    programming4us