Using the Policy Injection Application Block in ASP.NET

Using the Policy Injection Application Block in ASP.NET

ne technique becoming increasingly popular with developers is the adoption of an Aspect-Oriented Programming (AOP) model. AOP provides techniques for changing the behavior of business objects and other classes through the application of policies, making it easier to implement common crosscutting concerns such as logging, validation, exception handling, caching, and more.

The terminology of AOP uses the word “concern” to mean a task or feature of an application. Core concerns are the features usually unique to a class or object, such as extracting specific data from a database, or calculating the result of a function directly applicable to the class or object. Tasks common to more than one class or object are crosscutting concerns. Poor management of these can result in duplicated and hard-to-manage code, and unreliable applications.

Policy injection provides one approach to simplifying and unifying the implementation of crosscutting concerns. This is a feature introduced by the Microsoft patterns & practices (p&p) group into the latest release (version 3.0) of Enterprise Library. This new Enterprise Library version contains the Policy Injection Application Block, which integrates with the other application blocks in the library to support simple management across applications and business objects of features such as logging, exception handling, caching, validation, authorization, and instrumentation.

About the Policy Injection Application Block
The Policy Injection Application Block supports the application of policies for managing crosscutting concerns through an interception method that creates a handler pipeline and injects handlers into that pipeline. As the application makes calls to methods and properties of the target object, the handler pipeline executes each handler in turn?both on the way to the target object (the pre-processing stage) and on the way back (the post-processing stage). Each handler can perform tasks that carry out a required feature, such as logging or validation.

The Policy Injection Application Block is highly flexible and extensible. A set of built-in handlers provided with the block perform the common tasks exposed by the other application blocks within Enterprise Library. Developers can write custom handlers to accomplish almost any other tasks their applications require. They can even integrate these custom handlers with the Enterprise Library configuration system, making it simple to add policy-based configuration?in exactly the same way as the built-in handlers.

Developers, administrators, and operators can create handler pipelines in two ways. For developers, the direct route is to decorate classes and/or class members with the attributes exposed by the Policy Injection Application Block. For example, adding the [ValidationCallHandler] attribute to a class member specifies that the block should validate the parameters in line with specific validation attributes applied to each parameter.

For enterprise solutions, an alternative approach is the use of a configuration file or other configuration resource. Enterprise Library supports a range of configuration options, such as application configuration files (App.config and Web.config), custom configuration files, and configuration stored in a database. Developers, administrators, and operators can configure policies (including the addition of new policies) simply by editing the application configuration. This approach provides an excellent technique for managing applications post-deployment, and lets administrators change application behavior to meet changing conditions and requirements without requiring recompilation. In conjunction with the new Group Policy-driven configuration management features in Enterprise Library 3.0, this allows central administration of all computers in an Active Directory domain or forest that run the application.

Some common uses for the Policy Injection Application Block with the default set of handlers are:

  • Logging method calls and access to properties of the target object, and providing information about the context of the call and any parameter values provided.
  • Validating the values of parameters for methods and property Set accessors.
  • Caching the return value from methods and property Get accessors.
  • Handling exceptions in a structured way; for example, by wrapping or replacing them with other specific exception types.
  • Authorizing requests to target objects based on the current thread identity.
  • Measuring target object method and property execution times and exception generation rates by adding performance counters.

Many features of the Policy Injection Application Block make it easy to modify the block completely if the default implementation does not suit your requirements. For example, you can reuse the matching rules, handlers, policies, and other core types with your own interception mechanism if you create a custom proxy and injection pipeline generator.

Author’s Note: For more details of Enterprise Library, and to download the latest version, see

Using the Policy Injection Application Block
The Policy Injection Application Block includes:

  • A set of handlers for common Enterprise Library-related tasks
  • A set of attributes that apply these handlers to classes and class members
  • A set of matching rules that?when defined within a configuration policy?select the target classes and class members to which the block will apply the handlers

To use the configuration system to specify handlers for classes and class members, you define one or more policies using the Enterprise Library configuration tools. Each policy consists of a series of matching rules and a series of handlers. The matching rules select target classes and members; the block ANDs together the results within each policy. This provides a comprehensive range of options for selecting the target classes and members to which you want to apply handlers. For each class or member selected by the matching rules, the block then generates a handler pipeline containing the configured set of handlers for the selected classes and members.

The block performs the selection and generates the pipelines at start-up and caches them to reduce processing overheads. Subsequently, it injects pipelines only into the selected members?not into all the members of selected classes. Together with several other internal optimizations, this helps to minimize the extra overheads that most AOP and policy injection technologies incur.

Creating and Wrapping Target Objects
To allow the Policy Injection Application Block to inject handler pipelines into method and property calls, developers must use a specific technique when creating object instances. The block exposes two methods that generate a suitable proxy between the application and the target object. The PolicyInjection factory class provides the Create method to create new object instances from classes, and the Wrap method to apply policies to existing object instances.

Both of these are intelligent, in that they create a proxy to the target object only if there is at least one policy or handler to apply (at least one set of policy matching rules selects the target object, or a member carries a policy injection attribute). If there are no policies for the object, and no attributes on its members, the methods simply return the target object. The only overhead is the check through the cached configuration data and a scan for attributes on the members of the target class.

As long as the application creates instances of target objects using the Create method, or obtains references to existing instances using the Wrap method, the Policy Injection Application Block can apply the specified handlers. In particular, this approach allows administrators and operators to add new policies to existing objects simply by configuring suitable matching rules and handlers within these policies, without requiring any additional intervention from the developer or requiring recompilation and redeployment of the target objects, which avoids testing, versioning, and management issues.

There are some limitations with the Policy Injection Application Block, however, and it is important to consider these when planning to use it:

  • Target objects must either inherit from the MarshalByRefObject base class, or implement a known interface. The interface can be a custom interface created especially for the target object, as long as it declares all the methods and properties for which policy injection is required.
  • Policy injection can only take place for public members of the target class.
  • Matching rules can only select objects based on static information, because the selection process takes place only at application start-up.
  • Call handlers only have access to the information within the call message, and cannot maintain internal state.

The Built-in Matching Rules and Handlers
Before looking at how you can use the Policy Injection Application Block in ASP.NET applications, this section provides a brief overview of the default matching rules and handlers available within the block.

Matching Rules
The Policy Injection Application Block provides the following set of built-in matching rules for selecting classes, and members within these classes, to which it will apply a handler pipeline:

  • The AssemblyMatchingRule, which selects all the classes in a specified assembly.
  • The CustomAttributeMatchingRule, which selects classes or members decorated with an arbitrary custom attribute.
  • The MemberNameMatchingRule, which selects class members with one of a set of specified names.
  • The MethodSignatureMatchingRule, which selects class methods that have a specified signature.
  • The NamespaceMatchingRule, which selects classes in one of the specified namespaces.
  • The ParameterTypeMatchingRule, which selects class methods with a parameter name and type, or return value, that matches one of the specified types.
  • The PropertyMatchingRule, which selects class properties based on a set of specified names and containing the specified combination of Get and Set accessors.
  • The ReturnTypeMatchingRule, which selects class members that return an object of the specified type.
  • The TagAttributeMatchingRule, which selects class members decorated with a Tag attribute with a specified string.
  • The TypeMatchingRule, which selects classes of a specified type.

Call Handlers
The Policy Injection Application Block provides the following set of built-in handlers that you can add to a handler pipeline, using both the application configuration or directly applied attributes within the target class:

  • The Authorization Handler, which checks that the current thread identity (user) has permission to access the target class member based on a set of rules defined within configuration for the Security Application Block.
  • The Caching Handler, which uses the built-in ASP.NET caching mechanism to cache the return values from properties and methods of the target object.
  • The Exception Handling Handler, which uses an exception handling policy defined within the configuration of the Exception Handling Application Block to wrap or replace exceptions generated by code in the target object.
  • The Logging Handler, which filters, formats, and writes details of calls to target class members to the configured output (such as Windows Event Log, log files, and message queue systems).
  • The Performance Counters Handler, which updates a series of Windows performance counters each time the application makes a call to the members of the target object.
  • The Validation Handler, which validates values passed as parameters to target objects, based on either configuration of the Validation Application Block or validation attributes applied directly to parameters of the target members.

Policy Configuration Tools
If you apply policies using configuration, rather than through directly applied attributes, you can use one of the two configuration tools provided with Enterprise Library 3.0. The stand-alone Configuration Console allows you to create new configuration files and open existing ones, and then edit the contents before saving the file into the required location. The Enterprise Library section of your Start menu contains a link to open the Configuration Console.

Figure 1. The Enterprise Library Configuration Editors: The stand-alone Configuration Console (top) and the Visual Studio Configuration Editor (bottom) provide identical hierarchical views of configuration settings.

Alternatively, if you are using Visual Studio 2005 to create your application, you can use the Configuration Editor that Enterprise Library installs automatically. Simply right-click your existing application configuration file in Visual Studio’s Solution Explorer window and click “Edit Enterprise Library Configuration.”

Both editors work the same way, and provide an identical hierarchical view of the configuration settings. In the stand-alone Configuration Console, you edit the values for each node using the list of properties displayed in the right-hand window as you select each node. In the Visual Studio Configuration Editor, you edit the properties in the normal Visual Studio Properties window (see Figure 1).

Configuring an Application to use Policy Injection
To use Policy Injection, you must add the Policy Injection Application Block to your application configuration, even if you intend to directly apply attributes to configure handler pipelines for your target objects. In addition, if your attributes specify exception handling, logging, authorization, or a configured validation scheme, you must add the appropriate application blocks to the configuration as well as configuring the required settings in these blocks.

Also, bear in mind that, if you intend to run your ASP.NET application in partial trust mode, you must set the RequirePermission property for each block to False (the default is True). This prevents the blocks from demanding all the permissions they may use when they first load. If you subsequently use a feature of a block that requires permissions not available in your chosen partial trust mode (such as access to the file system or Windows Event Log), you can configure the relevant permissions for just the required features.

Author’s Note: For more details of running ASP.NET applications that use Enterprise Library in partial trust mode, see this article.

An ASP.NET Example Application
To demonstrate how you can use the Policy Injection Application Block in your ASP.NET applications, Figure 2 shows a simple example that uses most of the features of the block. The example provides buttons to execute several methods on two business objects, named AttributedCustomerModel and InterfaceCustomerModel. Both objects contain methods that access an XML file containing a list of customers. The InterfaceCustomerModel class also exposes a property, demonstrating how you can use the Policy Injection Application Block with target object properties as well as methods. You can download the example application in both VB.NET and C# versions.

Figure 2. Trace Information: The figure shows the sample application displaying the trace information.

In Figure 2, notice that the application has tracing enabled so you can see the messages generated by the members of the business objects as the main application code calls them (the screenshot has been altered to remove some of the ancillary details so that you can more easily see the tracing information, which helps to show the operation of handlers such as the Caching Handler).

Business Objects in the Example Application
The two business objects used in the example application demonstrate the two different types of target object for which the Policy Injection Application Block can create handler pipelines. The AttributedCustomerModel class (in the App_Code subfolder) inherits from MarshalByRefObject, and so the Create and Wrap methods of the block’s PolicyInjection class can create instances directly, building a suitable proxy and injecting a handler pipeline for any class members that have a policy defined in the configuration, or that carry handler attributes.

The second business object class, InterfaceCustomerModel, does not inherit from MarshalByRefObject, and so the example includes a interface definition (named ICustomerInterface) for this class that the Create and Wrap methods can use to create the appropriate proxy and handler pipelines. However, to demonstrate the way that the block relies on this interface, one of the public members of the InterfaceCustomerModel class does not exist in the interface definition. Table 1 shows the methods exposed by the two business objects.

MemberAttributed Customer ModelInterface Customer ModelNotes
GetCustomerName(String customerID)YesNo?
GetCustomerNameWithWildcard(String customerID)NoYesUses GetCustomerName method with a wildcard.
GetCustomerDetails(String customerID)YesYesNot defined in interface.
GetCityList(Int32 minimumCount)NoYes?
CityCountNoYesProperty. Uses GetCityList

The Example Application UI
The UI for the example application resides in one page named Default.aspx, seen in Figure 2. Each button has an event handler in the associated code-behind file Default.aspx.cs, which creates an instance of the appropriate target class and calls the required method. Depending on the type of data returned (a String, a DataRow, or a DataSet), the event handlers display it in the page. If an exception occurs, the text “ERROR:” followed by the exception message appears instead.

For the AttributedCustomerModel class, which inherits MarshalByRefObject, the event handlers can create an instance using the Create method and the class type:

   AttributedCustomerModel customers       = PolicyInjection.Create();

For the InterfaceCustomerModel class, which does not inherit MarshalByRefObject, the event handlers must specify the known interface for this class as well as the class type when they call the Create method:

   ICustomerInterface customers       = PolicyInjection.Create();

Note that this approach returns an object of the interface type and not the actual class type. This is because the proxy between the application and the target object can only see the members of the interface, and not members of the concrete class. If you try to cast the returned interface reference to a concrete type, the result is null?as demonstrated by this code in the event handler that attempts to get the customer details from the InterfaceCustomerModel class:

   ICustomerInterface customers      = PolicyInjection.Create();      // NOTE: this method is not declared in the ICustomerInterface interface.   // To access it, you might try to cast it to the concrete type. However,    // the following cast of the proxy to the concrete class returns null   InterfaceCustomerModel realObject = (customers as InterfaceCustomerModel);      // and so the following code will fail because realObject is null   DataRow[] details = realObject.GetCustomerDetails(      txtID_InterfaceCustDetails.Text);   if (details.GetLength(0) > 0)     ...

If you click the corresponding button in the example page, you will see that it produces an error, as shown in Figure 3.

Figure 3. Expected Error: The figure shows an error when attempting to access a member not declared in the interface.

The code in the event handler for the button gets a list of customers from the InterfaceCustomerModel class, demonstrating how you can use the Wrap method with an existing instance of a target object. The code first creates an instance of the InterfaceCustomerModel class using the new operator. The Policy Injection Application Block will not be able to see this object, and so cannot create a proxy and handler pipeline for it. However, calling the Wrap method with the interface type and passing the existing target object to it allows the block to create the required proxy and pipeline:

   InterfaceCustomerModel customerObject =       new InterfaceCustomerModel();      // now wrap the existing object so that PIAB can see it   ICustomerInterface customers          = PolicyInjection.Wrap(         customerObject);

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 NameMatching RulesCall Handlers
InterfaceModelPolicyMember Name = GetCustomerNameWithWildcard or GetCustomerListType Name = InterfaceCustomerModelLogging Handler with Categories = “AuditFile” and “EventLog”Caching Handler with cache duration 20 secondsException Handler with Exception Policy = “CustomerModelPolicy”
AttributeModelPolicyMethod Signature, Name = * and parameter = System.StringType Name = AttributedCustomerModelLogging Handler with Categories = “AuditFile”
CacheByTagPolicyTag 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.

Behavior of the Caching Handlers
The example application applies the Caching Handler in three different circumstances:

  • To the GetCustomerList method of the AttributedCustomerModel class through a directly applied attribute, as shown below:
  •    [CachingCallHandler(0, 0, 20)]   public DataTable GetCustomerList()   {     ...   }
  • To the InterfaceCustomerModel’s GetCustomerNameWithWildcard and GetCustomerList methods through the policy named InterfaceModelPolicy declared in the configuration.
  • To the InterfaceCustomerModel’s CityCount property through a Tag Attribute Handler defined in the policy named CacheByTagPolicy declared in the configuration, and applied to the method though a Tag attribute, as shown below:
  • ?
    Figure 5. Caching Handler Output: The figure shows the effect of the Caching Handler when calling a method in the target class.
       [Tag("ApplyTenSecondCaching")]   public Int32 CityCount   {     ...   }

When you access any of these members, the trace section of the page shows the calls made to the target member. However, if you repeat the call within the cache duration period, the trace section shows that the block only instantiated the target class (it has to do this to add the handler pipeline), and did not call the target method or property?as shown in Figure 5.

In this example, you can see that the call to InterfaceCustomerModel.GetCustomerNameWithWildcard calls the GetCustomerName method. However, on the subsequent request, the block calls neither of these methods and returns the value from the cache instead.

Author’s Note: The Caching Handler uses the built-in ASP.NET caching mechanism, which is domain-wide. The handler creates a cache key based on the complete signature of the current method, allowing it to vary the cache (create separate cached items) for calls that provide different parameters values. However, it does not detect and include the thread identity in the cache key, and so calls made on threads with different security contexts will return the same value from the cache. This may present a security risk if methods return sensitive or user-specific information.

Behavior of the Exception Handling Handler
The example application applies the Exception Handling Handler to only two methods, the GetCustomerNameWithWildcard and the GetCustomerList methods of the InterfaceCustomerModel class through the InterfaceModelPolicy declared in the configuration:

  • The configuration specifies the exception handling policy named CustomerModelPolicy, declared in the Exception Handling Application Block section, which will wrap any ArgumentNullException in a new Exception with a the message “You must specify a value for the customer ID.”
  • In the AttributedCustomerModel class, the GetCustomerName method throws an ArgumentNullException when there is no customerID:
   public String GetCustomerName(String customerID)   {     // ensure there is a customer ID specified     if (customerID == String.Empty)     {       throw new           ArgumentNullException("This exception will not be replaced...");     }     ... 

Therefore, as the attributes and configuration settings do not apply the Exception Handling Handler to this method, the page shows this error message:

ERROR: Value cannot be null. Parameter name: This exception will not be replaced...

GetCustomerNameWithWildcard also throws an ArgumentNullException when there is no customerID:

   public String GetCustomerNameWithWildcard(String customerID)   {     // ensure there is a customer ID specified     if (customerID == String.Empty)     {       throw new ArgumentNullException("This exception should be replaced...");     }     ...

This method does have the Exception Handling Handler attached, and so?when there is no customer ID?the page displays the following error message generated by the exception policy defined in the Exception Handling Application Block configuration:

ERROR: You must specify a value for the customer ID

Behavior of the Logging Handlers
The example application applies the Logging Handler in two circumstances:

  • To the InterfaceCustomerModel’s GetCustomerNameWithWildcard and GetCustomerList methods, the application apples the Logging Handler through the InterfaceModelPolicy declared in the configuration. This policy generates messages in the audit.log file and in the Windows Event Log.
  • To methods with any name that take a single parameter of type System.String, the application apples the Logging Handler through the AttributeModelPolicy declared in the configuration. This policy also uses a Namespace Matching Rule, and so it selects only the GetCustomerName and GetCustomerDetails methods of the AttributedCustomerModel class. This policy generates only audit.log file messages.

Executing one of the methods listed above should produce log messages in the relevant logs. For example, executing GetCustomerNameWithWildcard with the value “A” for the single parameter produces both a “Before” and “After” entry in the audit.log file. Here’s the content of the “After” message in the log file:

   Timestamp: 21/03/2007 10:50:01   Message: After   Category: AuditFile, EventLog   Type: InterfaceCustomerModel   Method: GetCustomerNameWithWildcard   Parameters: customerID : A   Return Value: Alfreds Futterkiste   Exception:    Call Time: 00:00:00.0002551   Priority: 0   EventId: 0   Severity: Information   Title: Call Logging   Machine: DIMINUTIVEC   Application Domain: f4e1bb0-9-128189471987530168   Process Id: 3724   Process Name: WebDev.WebServer.EXE   Win32 Thread Id: 2412   Thread Name:
Figure 6. Event Log Entries: Here’s a Logging Handler entry in the Windows Event Log.

You can see that the audit.log file message contains a wealth of information, including the target type name, method name, parameters, return value, call duration (Call Time), and more. You can configure for more or less information using the Logging Handler settings, or in the Logging Application Block section.

The call to the GetCustomerNameWithWildcard method also generates “Before” and “After” entries in Windows Event Log, containing the same information as the audit.log file entry. Figure 6 shows the same “After” message generated by the Logging Block in Windows Event Log.

You can execute the other methods to which this handler applies, and view the results in the audit.log file and (for the InterfaceCustomerModel.GetCustomerNameWithWildcard and the InterfaceCustomerModel.GetCustomerList methods) in the Windows Event Log. However, you will discover that the AttributedCustomerModel.GetCustomerName method does not generate any log file entries, even though the matching rules for the AttributeModelPolicy declared in the configuration select this method. This is because, as you saw earlier, this method carries the ApplyNoPolicies attribute:

   [ApplyNoPolicies]   public String GetCustomerName(String customerID)   {     ...   }

The ApplyNoPolicies attribute overrides the configuration, and prevents the block from applying the configured policy to this member.

Behavior of the Validation Handlers
The example application applies the Validation Handler in only one circumstance?for the AttributedCustomerModel.GetCustomerDetails method through a directly applied attribute:

   [ValidationCallHandler]   public DataRow[] GetCustomerDetails([StringLengthValidator(      5, RangeBoundaryType.Inclusive,       5, RangeBoundaryType.Inclusive)]       String customerID)   {     ...   }

If you execute this method with a customer ID consisting of anything other than five characters, you will see the error raised by the Validation Application Block:

   ERROR: Parameter validation failed Parameter name: customerID

There are many ways that you can set up validation using the Validation Application Block, in particular by creating Rule Sets that can customize the validation error message. There is also a huge range of validation types you can take advantage of in your application configuration, or as validation attributes on parameters.

Author’s Note: If you decide to experiment with the example by validating methods of the InterfaceCustomerModel class (such as GetCityList) using attributes, you must apply the [ValidationCallHandler] attribute to the method declaration in the concrete InterfaceCustomerModel class, but apply the validation attributes such as a [RangeValidator] to the declaration of the method in the ICustomerInterface. This is required because, as you saw earlier, the Policy Injection Application Block cannot see the original class through the proxy it creates.

In this article you have seen one of the latest additions to Enterprise Library?and its use within a simple ASP.NET example application. Microsoft’s patterns & practices group added a raft of new and updated features to version 3.0 of Enterprise Library, including the Policy Injection Application Block described here?a new block that provides a flexible, configurable, and extensible solution for managing crosscutting concerns in enterprise-level applications.

The Policy Injection Application Block allows developers, administrators, and operators to change the behavior of business objects and target classes by injecting a pipeline containing handlers between the client application code and members of the target class. These handlers can help to minimize crosscutting concerns by implementing tasks such as validation, caching, logging, and authorization with no extra effort required by developers or administrators. Instead, the handlers integrate with the other application blocks within Enterprise Library and take advantage of the features they expose.

Developers can hard-code policies into objects using attributes, and administrators can add, remove, or modify policies using the configuration tools. In conjunction with new Group Policy configuration management capabilities within Enterprise Library, The Policy Injection Application Block provides a simple to use, yet enterprise-wide and powerful technique for managing ancillary tasks and crosscutting concerns.

In addition, developers can extend the Policy Injection Application Block by creating new handlers, handler attributes, and matching rules. They can even modify the block to change the interception and pipeline injection mechanism to suit their specific requirements.


About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist