Chapter 4. Exception Handling Application Block

To err is human, and we developers are but humans. It's a myth that we can develop bug-free software at one go. We can definitely take measures to reduce bugs through test-driven development, unit test cases, stringent code check-in policy, and so on. However, the fact is that there are bugs in every application and they will show their ugly faces in the production environment. Additionally, applications have to face unforeseen scenarios such as the database server not being available, network failure, and so on. Hence, handling exceptions and providing meaningful and user-friendly messages to the user helps in avoiding/reducing user frustration. We need to handle exceptions not only to gracefully recover but also to log useful information, which can be used to fix bugs in the application.

Many good developers or project teams develop reusable components to handle and manage exceptions within and across software projects. Unfortunately, developing a good reusable component that caters to various requirements involves huge cost and effort, and also, maintenance of such in-house components is a nightmare. The Exception Handling Application Block is a reusable library that addresses many common requirements that developers have to deal with and there is enough room for extensibility through custom implementation to satisfy unique requirements. The beauty of the application block lies in its design. We have to sprinkle very much less code in our application to manage exceptions. The configuration determines how an exception is processed and the application code dictates which policy processes the exception. This flexibility allows the application to modify the exception handling process without recompiling the code.

In this chapter, you will:

  • Receive an overview of the Exception Handling Application Block
  • Be introduced to concepts such as Exception Policy, Exception Types, and Exception Handlers
  • Learn about referencing the required and optional assemblies
  • Learn about the initial infrastructure configuration using the configuration editor
  • Learn about adding a namespace to avoid fully qualifying types
  • Learn how to wrap exceptions using Wrap Handler
  • Learn how to replace exceptions using Replace Handler
  • Learn how to log exception information using Logging Handler
  • Learn how to shield exceptions in WCF Service using ExceptionShielding
  • Learn how to implement a custom Exception Handler

Developing an application

Before we leverage and dig deeper into individual features of the Exception Handling block, we will create a simple application that will help us to get up-to-speed with the basics. In this section, we will do the following:

  • Reference the Exception Handling block assemblies
  • Set up the initial configuration
  • Add namespaces

To complement the concepts and sample code of this book and allow you to gain quick hands-on experience of different features of the Exception Handling Application Block, we have created a sample demonstration application, which simulates different layers of an application.

A screenshot of the sample application follows:

Developing an application

Referencing required assemblies

For the purposes of this demonstration, we will be referencing non-strong-named assemblies but, based on individual requirements, Microsoft strong-named assemblies or a modified set of custom assemblies can be referenced as well.

The following table lists the required/optional assemblies:

Assembly

Required/Optional

Microsoft.Practices.EnterpriseLibrary.Common.dll

Required

Microsoft.Practices.ServiceLocation.dll

Required

Microsoft.Practices.Unity.dll

Required

Microsoft.Practices.Unity.Interception.dll

Required

Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.dll

Required

Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.dll

Optional

Used while leveraging Logging functionality

Microsoft.Practices.EnterpriseLibrary.Data.dll

Optional; used only if exception logging is configured to be stored in database

Adding initial Exception Handling settings

Before we can leverage the features of the Exception Handling block, we have to add the initial Exception Handling Settings to the configuration. Open the Enterprise Library configuration editor either using the shortcut available in Start | All Programs | Microsoft patterns & practices | Enterprise Library 5.0 | Enterprise Library Configuration or just by right-clicking the configuration file in the Solution Explorer window of Visual Studio IDE and clicking on Edit Enterprise Library V5 Configuration. Initially, we will have a blank configuration file with default Application Settings and Database Settings.

The following screenshot displays the default settings displayed in the configuration editor:

Adding initial Exception Handling settings

Let us go ahead and add the Exception Handling Settings in the configuration file. Select the menu option Blocks, which lists many different settings to be added to the configuration, and click on the Add Exception Handling Settings menu item to add the configuration settings.

The following screenshot shows the menu option Add Exception Handling Settings:

Adding initial Exception Handling settings

Once we click on Add Exception Handling Settings the configuration editor will display the default Exception Handling Settings as shown in the following screenshot:

Adding initial Exception Handling settings

Notice that the settings consist of three sections: Policies, Exception Types, and Handlers. By default, a policy named Policy with exception type All Exceptions is added to the configuration. We will change the default configuration later, but for now, we are in good shape with regards to the initial infrastructure configuration.

Adding namespaces

Instead of fully qualifying the type on every instance of its usage, we can add the namespace given below to the source code file to use the Exception Handling block elements without fully qualifying the reference.

Core Namespace:

  • Microsoft.Practices.EnterpriseLibrary.ExceptionHandling

Configuration Namespace (Optional): Required while using the EnterpriseLibraryContainer to instantiate objects.

  • Microsoft.Practices.EnterpriseLibrary.Common.Configuration

Unity Namespace (Optional): Required while instantiating objects using UnityContainer.

  • System.Configuration
  • Microsoft.Practices.Unity
  • Microsoft.Practices.Unity.Configuration

WCF Namespace (Optional): Required while leveraging the Exception Handling block in a WCF Service.

  • Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.WCF

Understanding the Exception Handling block

The Exception Handling Application Block is driven by elements such as Exception Policy, Exception Types, Exception Handler and the ExceptionManager class.

Exception policy

Exception policy is like creating a group under which one or more exception types are configured and under each exception type, one or more handlers can be configured. For example, we might have Data Access Exception Policy to handle data access-related exceptions with multiple exception types such as DBConcurrencyException, DbException, and so on. While configuring the exception policy we have to provide a unique name, which can be used in the application code to process the exception.

The following class diagram shows the method exposed by the ExceptionPolicy class:

Exception policy

Exception types

Exception type is nothing but any type that inherits from System.Exception; based on the configuration the application block chooses the matching exception type in the class hierarchy. If an exception of type System.NotFiniteNumberException is thrown and the policy is configured to handle exceptions of types System.Exception and System.ArithmeticException then the application block will process the exception using System.ArithmeticException based on the class hierarchy. While configuring the exception type, we have to decide on the post handling action. There are three options to choose from.

  • None: Indicates to the calling code to continue execution.
  • NotifyRethrow: Indicates to the calling code to throw the same exception.
  • ThrowNewException: Indicates that the application block will throw an exception after executing all the configured handlers and the exception will be a result of the executed handlers.

Exception handler

Exception handlers are .NET classes that implement the Exception Handling block's interface called IExceptionHandler. The application block includes the four commonly required handlers Wrap, Replace, Logging, and Fault Contract Exception Handler (used to guard the WCF service boundary and generate new fault contract from the exception). We can also implement custom handlers to meet our custom requirements and configure them in the configuration file using the editor.

The following class diagram shows various concrete implementations of exception handlers and the IExceptionHandler interface:

Exception handler

The description of each of the concrete exception handlers is given as follows:

  • Wrap Handler: The Wrap handler is very useful in scenarios where we want to provide a more meaningful message to the calling code rather than throwing the original exception. The original exception is wrapped with another exception that gives more detailed information to the caller. This exception handling pattern is referred to as the Exception Translation pattern.
  • Replace Handler: The Replace handler as the name suggests replaces the original exception with the configured exception type; this avoids revealing sensitive information to the calling code. This exception handling pattern is referred to as the Exception Shielding pattern.
  • Logging Handler: Handling exceptions is not enough; as developers we have to identify issues and resolve them. The Logging handler leverages the Logging Application Block to log exception details, which helps in issue identification and resolution. This exception handling pattern is referred to as the Exception Logging pattern.
  • WCF Fault Contract Exception Handler: This guards the WCF service boundary and generates a new FaultContract from the exception; developers working on the WCF service would appreciate the ability to shield the exception and return the configured FaultContract based on the exception type as part of the response.
  • Custom Exception Handler: Out of luck? None of the out-of-the-box handlers fits your requirement? Extensibility is the key aspect of the Enterprise Library; we can always write a custom exception handler by implementing the IExceptionHandler interface.

Exception Manager class

ExceptionManager is one of the key classes of the Exception Handling Application Block; this abstract class is part of the Microsoft.Practices.EnterpriseLibrary.ExceptionHandling namespace. It acts as an entry point to the exception handling functionality and provides two different ways to manage exceptions. The signatures of both the HandleException and Process methods are given next. The actual implementation is provided by the ExceptionManagerImpl class, which inherits from the ExceptionManager class.

The following class diagram shows the inheritance hierarchy and methods exposed by ExceptionManager and the ExceptionManagerImpl class:

Exception Manager class

HandleException method

The HandleException method provides granular control while processing exceptions; it returns a Boolean value indicating whether or not an exception re-throw is recommended. Typical usage of the HandleException method will be similar to the code snippet given next:

try
{
BusinessLayer.BlogManager blogManager = new BusinessLayer.BlogManager();
//Get Blog Post
BusinessLayer.BlogPost post = blogManager.GetBlogPost(0);
}
catch (ArgumentException ex)
{
Exception exceptionToRethrow;
//Get instance of ExceptionManager using static method of Enterprise Library Container
ExceptionManager exManager = EnterpriseLibraryContainer.Current.GetInstance<ExceptionManager>();
//Call to HandleException method
//Return value indicates whether to re-throw the exception
bool rethrow = exManager.HandleException(ex, "General Policy", out exceptionToRethrow);
if (rethrow) throw exceptionToRethrow;
}

Process method

The Process method automatically performs exception management and throws the exception based on the configuration. It accepts the policy name and a delegate or a lambda expression; the application block manages any exception that occurs while executing the method or lambda expression, also if the postHandlingAction is set to ThrowNewException then the application block throws the exception as a result of the respective execution of the configured exception handlers.

Typical usage of the Process method will be similar to the code snippet given next:

//Get instance of ExceptionManager using static method of Enterprise Library Container
ExceptionManager exManager = EnterpriseLibraryContainer.Current.GetInstance<ExceptionManager>();
BusinessLayer.BlogPost post = null;
BusinessLayer.BlogManager blogManager = new BusinessLayer.BlogManager();
//try..catch block not required...
//Automatic Exception Management through Process method
post = exManager.Process<BusinessLayer.BlogPost>(
() => { return blogManager.GetBlogPost(0); },
"Data Access Policy"
);

Stitching together: Exception Policy/Type/Handler

Let us stitch together the three fundamental elements (exception policy/type/handler) to put things in perspective and understand them better. Imagine that we want all the database-related exceptions to be replaced with a new exception to prevent disclosing the connection string information; additionally, we want to log the exception in a file to identify the root cause of the exception. To achieve this, we define a policy named Data Access Exception Policy. Now we can associate one or more data access-related exception types (SqlException, SqlTypeException, DBConcurrencyException, and so on) and configure one or more exception handlers for each exception type. As we want to replace the exception and also log the exception information, we can configure the Logging handler first and then the Replace handler.

Creating an Exception Handling block object

We have several options at hand while creating an Exception Handling object such as using the static ExceptionPolicy class, using Unity service locator, and using Unity container directly. A few approaches such as configuring the container through a configuration file or code are not listed here but the recommended approach is either to use the Unity service locator for applications with few dependencies or create objects using Unity container directly to leverage the benefits of this approach. Use of the static factory class is not recommended.

Using the ExceptionPolicy class

ExceptionPolicy is a static class and is part of the Microsoft.Practices.EnterpriseLibrary.ExceptionHandling namespace. This class contains static methods to handle exceptions. Internally, it leverages EnterpriseLibraryContainer, which is part of the Microsoft.Practices.EnterpriseLibrary.Common.Configuration namespace. This class is an entry point for the container infrastructure for the Enterprise Library. The ExceptionPolicy class was the default approach to handle exceptions in versions prior to 5.0. This approach is no longer recommended and is still available for backwards compatibility.

The following is the syntax to handle exceptions using the ExceptionPolicy static class:

try
{
//Potentially exceptional area :)
}
catch (Exception ex)
{
bool rethrow = ExceptionPolicy.HandleException(ex, "UI Policy");
if (rethrow)
{
throw;
}
}

Using Unity service locator

This approach is recommended for applications with few dependencies. The EnterpriseLibraryContainer class exposes a static property called Current of type IServiceLocator, which resolves and gets an instance of the specified type.

The following is the syntax to create an instance of ExceptionManager using Unity service locator:

//Get instance of ExceptionManager using static method of Enterprise Library Container
ExceptionManager exManager = EnterpriseLibraryContainer.Current.GetInstance<ExceptionManager>();

Using Unity container directly

Larger complex applications demand looser coupling. This approach leverages the dependency injection mechanism to create objects instead of explicitly creating instances of concrete implementations. Unity container resolves objects using type registrations and mappings; these can be configured programmatically or through a configuration file. Based on the configuration, it resolves the appropriate type whenever requested. The following example instantiates a new Unity container object and adds the Enterprise Library Core Extension. This loads the configuration and makes registrations and mappings of Enterprise Library available.

The following is the syntax to create an instance of ExceptionManager directly using Unity Container:

var container = new UnityContainer();
container.AddNewExtension<EnterpriseLibraryCoreExtension>();
ExceptionManager exManager = container.Resolve<ExceptionManager>();
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.113.55