Handler Attributes in the Example Application
The AttributedCustomerModel class, as the name suggests, demonstrates the use of handler attributes. For example, the
GetCustomerList method carries the
CachingCallHandler attribute, specifying the cache duration as 20 seconds:
[CachingCallHandler(0, 0, 20)]
public DataTable GetCustomerList()
{
...
}
This use of the
CachingCallHandler attribute takes advantage of a constructor that accepts a cache duration value as a number of hours, minutes, and seconds. If you omit these parameters and use the default attribute constructor, the default cache duration is five minutes.
The
GetCustomerDetails method of the AttributedCustomerModel class carries the
ValidationCallHandler attribute. This attribute takes advantage of the capabilities of the Validation Application Block, which exposes a comprehensive set of validation features. As with the Policy Injection Application Block, you can apply these features using validation attributes, or by configuring Rule Sets that define the validation rules to apply to a specific member of a class. In general, unless you need to reuse Rule Sets, the easiest approach is to use validation attributes as shown here:
[ValidationCallHandler]
public DataRow[] GetCustomerDetails(
[StringLengthValidator(5, RangeBoundaryType.Inclusive,
5, RangeBoundaryType.Inclusive)]
String customerID)
{
...
}
The
GetCustomerDetails method takes a single parameter named
customerID, which you can see at the end of the opening method declaration. This parameter carries a
StringLengthValidator attribute, which specifies that the string passed in the
customerID parameter must be exactly five characters (the minimum and maximum values are "5" and the boundaries are "inclusive").
The remaining method in the AttributedCustomerModel class,
GetCustomerName, carries a special attribute that prevents the block from applying any policy defined in the configuration, even if the corresponding matching rules select this method. This is useful for methods where, at the design and development stage, you know that you do not want administrators or operators to apply any policies to specific methods:
[ApplyNoPolicies]
public String GetCustomerName(String customerID)
{
...
}
Author's Note: You can use handler attributes on a class declaration to apply to all the members of a class, or on individual class members. You can also use attributes both in classes that inherit MarshalByRefObject, and in classes that depend on an interface for policy injection. However, when using an interface definition to apply policy injection, you will find that the Validation Handler requires the parameter validation attributes to exist in the interface definition rather than the concrete class definition. |
Configuration Settings for the Example Application
 | |
Figure 4. Example Application Configuration: The figure shows the Enterprise Library configuration for the example application. |
The example application shows several of the ways that you can select target classes and class members using matching rules defined in the application configuration, and how you can use the four handlers most useful in ASP.NET applications: the Caching, Exception, Logging, and Validation handlers.
Figure 4 shows the configuration file for the application open in the Visual Studio Configuration Editor. You can see that it contains the Data Access Application Block, Exception Handling Application Block, Logging Application Block, and the Policy Injection Application Block (the example does not actually use the Data Access Application Block, but the configuration tool adds this by default).
The Exception Handling Block configuration defines a simple single exception policy named
CustomerModelPolicy, which will wrap any ArgumentNullException passed to it in a standard Exception with the message "You must specify a value for the customer ID".
The Logging Application Block configuration defines two category sources that the example application can use to generate log messages. The AuditFile category source writes log messages into a disk file named
audit.log, located in the local
C:\Temp folder. The EventLog category generates event entries in the Application section of the Windows Event Log. All these settings are, of course, configurable within the Logging Application Block section if you want to implement a different logging strategy.
The settings for the Policy Injection Application Block come next. These consist of three policies, described in detail in Table 2.
Policy Name |
Matching Rules |
Call Handlers |
InterfaceModelPolicy |
Member Name = GetCustomerNameWithWildcard or GetCustomerListType Name = InterfaceCustomerModel |
Logging Handler with Categories = "AuditFile" and "EventLog"Caching Handler with cache duration 20 secondsException Handler with Exception Policy = "CustomerModelPolicy" |
AttributeModelPolicy |
Method Signature, Name = * and parameter = System.StringType Name = AttributedCustomerModel |
Logging Handler with Categories = "AuditFile" |
CacheByTagPolicy |
Tag Attribute = "ApplyTenSecondCaching" |
Caching Handler with cache duration of 10 seconds |
In the example application, you'll see how the combination of policies (such as those in Table 2) and attributes defined within the business rules provides a flexible mechanism for applying handlers to target objects and managing crosscutting concerns.