Walkthrough: Policy Injection in an ASP.NET Application

Retired Content

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

The latest Enterprise Library information can be found at the Enterprise Library site.

Over the many years that developers have been creating traditional executable applications, and more recently Windows Forms applications, they have evolved architectural patterns and design philosophies that simplify application development, reduce development time, minimize errors, and maximize the capabilities and manageability of applications. However, the advantages these approaches offer are not confined to traditional executable applications—they are equally valid in Web development, where applications continue to become larger, more complex, and increasingly mission-critical for organizations and governments.

Like traditional executable applications, Web applications contain crosscutting concerns such as logging, caching, validation, and exception management—the Policy Injection Application Block can help minimize the issues involved in implementing these features.

This Walkthrough shows a common scenario that contains all the aforementioned crosscutting concerns and uses the Policy Injection Application Block to implement them in a manageable and configurable way. It displays a single ASP.NET page that allows users to execute the following three functions, each of which calls a method in a separate business object class named CustomerModel:

  • Get a list of customers using the GetCustomerList method. This method takes no parameters and returns a DataSet instance that contains a list of all customers.
  • Find the name of a specific customer from their customer ID using the GetCustomerName method. This method takes a customer ID as a parameter and returns a string that contains the name of the specified customer.
  • Get all the available information about a specific customer using the GetCustomerDetails method. This method takes a customer ID as a parameter and returns a DataRow instance that contains details about the specified customer.

To allow the Policy Injection Application Block to create and attach a handler pipeline to the CustomerModel class, the business object class derives from MarshalByRefObject. An alternative approach would be to define an interface for the class, and use the interface as the basis for the application block to carry out the policy injection process.

Figure 1 illustrates the ASP.NET page displaying the list of customers (only the first few are visible in the screen shot).

Ff649773.2c1c742c-8353-4856-af73-37d79efb9ac3(en-us,PandP.10).png

Figure 1
The list of customers displayed by the example ASP.NET application

To understand the configuration the application uses, see the following sections and topics:

The ASP.NET Walkthrough Configuration

The Web.config file for the application has the Policy Injection Application Block configured and specifies a single policy named MyPolicy. This policy (see Figure 1) includes two matching rules: the Member Name Matching Rule and the Type Matching Rule; and three handlers: the Logging Handler, Caching Handler, and Exception Handler.

Ff649773.1670b773-c61b-47ad-a656-2216e507392b(en-us,PandP.10).png

Figure 1
The configuration settings and files for the example ASP.NET application

The Member Name Matching Rule selects class members named GetCustomerList and GetCustomerName; the Type Matching Rule selects target object types named CustomerModel. Therefore, the policy and its associated handlers only apply to the first two methods in the business object.

The Logging Handler is configured to log before and after the call, and it specifies two categories named Audit and General; therefore, it will create log entries before and after each call to methods of the business object to which the policy applies. The two categories are configured in the Category Sources section of the Logging Application Block (shown in Figure 1) and instruct the Logging Application Block to write log messages to both a log file (named Audit.log) and the Windows Event Log.

The Caching Handler specifies caching of the return values from the two methods to which the policy applies, with an expiration time of 20 seconds.

The Exception Handler configuration specifies that it will apply the exception handling policy named CustomerModelPolicy (visible in the Exception Handling Application Block section in Figure 1), which traps any exceptions of type ArgumentNullException and wraps them with a new Exception containing the message, "You must specify a value for the customer ID."

Finally, the business object itself applies the Validation Handler, using an attribute placed directly on just the third method, GetCustomerDetails. This attribute specifies that the customerID parameter (a String) must be exactly five characters, as shown in the following code.

[ValidationCallHandler]
public DataRow[] GetCustomerDetails( 
       [StringLengthValidator(5, RangeBoundaryType.Inclusive,
        5, RangeBoundaryType.Inclusive)] String customerID)
{
  ... method implementation here ...
}
'Usage
<ValidationCallHandler()> _
Public Function GetCustomerDetails( _
     <StringLengthValidator(5, RangeBoundaryType.Inclusive, _
      5, RangeBoundaryType.Inclusive)> ByVal customerID As String) As DataRow()

  ... method implementation here ...

End Function

Another relevant feature of the business object is that it writes messages to the ASP.NET trace mechanism in the constructor and in each method. It uses the Warn method of the current HTTP Context.

HttpContext.Current.Trace.Warn("CustomerModel", "GetCustomerDetails executed");
'Usage
HttpContext.Current.Trace.Warn("CustomerModel", "GetCustomerDetails executed")

The GetCustomerName and GetCustomerDetails methods of the business object also check for the presence of a customer ID in the parameter passed to the method; if there is not a customer ID in the parameter, they throw an ArgumentNullException.

// Ensure there is a customer ID specified.
if (customerID == String.Empty)
{
  throw new ArgumentNullException("This exception will be replaced...");
}
'Usage
' Ensure there is a customer ID specified.
If customerID = String.Empty Then
  Throw New ArgumentNullException("This exception will be replaced...")
End If

Notice the message in the exception, which the Policy Injection Application Block's Exception Handler will replace with a new exception for the GetCustomerName method (to which the policy applies).

Other than the configuration settings in Web.config, and the ValidationCallHandler on the GetCustomerDetails method, no code directly aimed at managing crosscutting concerns exists in the business object or in the default ASP.NET page. The only difference from standard coding practice is that the handlers for the buttons on the ASP.NET page instantiate the business object using the Create method of the Policy Handler Application Block factory class, as shown in the following code.

CustomerModel customers = PolicyInjection.Create<CustomerModel>();
'Usage
Dim customers As CustomerModel = PolicyInjection.Create(Of CustomerModel)()