Exception Handling Application Block In Microsoft Enterprise Library 6.0

 

Introduction

 
Exception handling is one of the most important tasks in any application. Many applications either do not handle applications or they handle it in an Adhoc manner.
 
In this section, we will see how we can use the readymade exception handling block so that we need not code, and build error handling routines from scratch.
 
How
 
We have to install Enterprise Library – Exception Handling Application Block from NuGet Packages.
 
.net
 
.net
 
Install Enterprise Library – Exception Handling Application Block Logging Handler from NuGet Packages to log the exceptions that are going to be thrown by the application.
 
.net
 
.net
 
Microsoft Enterprise Library Configuration Tool
 
This tool will be used to configure different blocks for the application. Now, we need to install the Microsoft Enterprise Library from the below URL by following the installation instructions.
 
As in this article, we are just going to discuss the Exception Application Block, we will now configure the exception handling configuration details for our application.
 
Please follow the configuration steps below
 
Right-click on the App.config >> Open with Enterprise Library Application Block Console. If it is not available in the list, you can add it manually by clicking on the "Add" button.
 
.net
 
.net
 
.net
 
.net
 
.net
 
.net
 
.net
 
.net
 
Using Exception Handlers
 
The Exception Handling Application Block is designed to support the typical code contained in catch statements in application components. Instead of repeating this code (such as - logging exception information), throughout the identical catch blocks in an application component, the application block allows developers to encapsulate this logic as reusable exception handlers.
 
Exception handlers are .NET classes that encapsulate exception handling logic and implement the Exception Handling Application Block interface named IExceptionHandler.
 
The Exception Handling Application Block includes five exception handlers:
  • Wrap Handler
     
    This exception handler wraps one exception around another.
     
  • Replace Handler
     
    This exception handler replaces one exception with another.
     
  • Logging Exception Handler
     
    This exception handler formats exception information, such as the message and the stack trace. Then the logging handler gives this information to the Enterprise Library Logging Application Block so that it can be published.
     
  • Fault Contract Exception Handler
     
    This exception handler is designed for use at Windows Communication Foundation (WCF) service boundaries and generates a new Fault Contract from the exception.
     
  • Custom Exception Handler
     
    This exception handler is designed to create our own custom exception handlers.
In this article, we are going to cover Wrap, Replace, and Logging Exception Handler.
 
.net
 
.net
 
.net
 
.net
 
.net
 
In the same way, we can configure the settings for Replace Handler also. The total configuration will look something like the image shown below:
 
.net
 
Now, we are done with our configuration for the Exception Handling Block; and, we are going to configure the Logging Application Block here to log the exceptions that are going to be thrown by our application.
 
I am not going to explain regarding configuring Logging Application Block here as we have already covered that in my previous article. Click here to have a look at the Logging Application Block.
 
After configuring the Exception Handling and Logging Block, the configuration tool will look as below.
 
.net
 
All the above configuration will generate the below sections in our App.config.
 
You can directly add the below configuration blocks to your App.config under <configuration> section if you don’t want to configure through the configuration console.
  1. <configSections>  
  2.      <section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />  
  3.      <section name="exceptionHandling" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Configuration.ExceptionHandlingSettings, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />  
  4. </configSections>  
  5. <loggingConfiguration name="" tracingEnabled="false" defaultCategory="General" logWarningsWhenNoCategoriesMatch="false">  
  6.      <listeners>  
  7.           <add name="Rolling Flat File Trace Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.RollingFlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.RollingFlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" fileName="RollingFlatFile.log" footer="----------------------------------" formatter="Text Formatter" header="" rollInterval="Day" traceOutputOptions="DateTime, Timestamp" filter="All" />  
  8.           <add name="Event Log Trace Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FormattedEventLogTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FormattedEventLogTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" source="Application" formatter="Text Formatter" log="Application" machineName="." traceOutputOptions="None" />  
  9.      </listeners>  
  10.      <formatters>  
  11.           <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" template="Timestamp: {timestamp(local)}{newline}    
  12. Message: {message}{newline}    
  13. Category: {category}{newline}    
  14. Priority: {priority}{newline}    
  15. Severity: {severity}" name="Text Formatter" />  
  16.      </formatters>  
  17.      <categorySources>  
  18.           <add switchValue="All" autoFlush="true" name="General">  
  19.                <listeners>  
  20.                     <add name="Rolling Flat File Trace Listener" />  
  21.                     <add name="Event Log Trace Listener" />  
  22.                </listeners>  
  23.           </add>  
  24.      </categorySources>  
  25.      <specialSources>  
  26.           <allEvents switchValue="All" name="All Events">  
  27.                <listeners>  
  28.                     <add name="Rolling Flat File Trace Listener" />  
  29.                </listeners>  
  30.           </allEvents>  
  31.           <notProcessed switchValue="All" name="Unprocessed Category">  
  32.                <listeners>  
  33.                     <add name="Rolling Flat File Trace Listener" />  
  34.                </listeners>  
  35.           </notProcessed>  
  36.           <errors switchValue="All" name="Logging Errors & Warnings">  
  37.                <listeners>  
  38.                     <add name="Rolling Flat File Trace Listener" />  
  39.                </listeners>  
  40.           </errors>  
  41.      </specialSources>  
  42. </loggingConfiguration>  
  43. <exceptionHandling>  
  44.      <exceptionPolicies>  
  45.           <add name="ExceptionHandling">  
  46.                <exceptionTypes>  
  47.                     <add name="Base Exception Handler" type="System.Exception, mscorlib,   Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" postHandlingAction="ThrowNewException">  
  48.                          <exceptionHandlers>  
  49.                               <add name="Base Wrap Handler" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.WrapHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling" exceptionMessage="Exception occurred in application." wrapExceptionType="System.ApplicationException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />  
  50.                               <add name="Logging Exception Handler" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.LoggingExceptionHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" logCategory="General" eventId="9000" severity="Error" title="ExceptionHandlingBlock" formatterType="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.TextExceptionFormatter, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" priority="5" />  
  51.                          </exceptionHandlers>  
  52.                     </add>  
  53.                     <add name="DivideByZero Exception Handler" type="System.DivideByZeroException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" postHandlingAction="ThrowNewException">  
  54.                          <exceptionHandlers>  
  55.                               <add name="DivideByZero Replace Handler" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.ReplaceHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling" exceptionMessage="Divide By Zero Exception Occurred." replaceExceptionType="System.ApplicationException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />  
  56.                               <add name="Logging Exception Handler" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.LoggingExceptionHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" logCategory="General" eventId="9000" severity="Error" title="ExceptionHandlingBlock" formatterType="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.TextExceptionFormatter, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" priority="5" />  
  57.                          </exceptionHandlers>  
  58.                     </add>  
  59.                     <add name="FileNotFound Exception Handler" type="System.IO.FileNotFoundException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" postHandlingAction="ThrowNewException">  
  60.                          <exceptionHandlers>  
  61.                               <add name="FileNotFound Replace Handler" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.ReplaceHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling" exceptionMessage="FileNotFound Exception Occurred." replaceExceptionType="System.ApplicationException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />  
  62.                               <add name="Logging Exception Handler" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.LoggingExceptionHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" logCategory="General" eventId="9000" severity="Error" title="ExceptionHandlingBlock" formatterType="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.TextExceptionFormatter, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" priority="5" />  
  63.                          </exceptionHandlers>  
  64.                     </add>  
  65.                </exceptionTypes>  
  66.           </add>  
  67.      </exceptionPolicies>  
  68. </exceptionHandling> 
Now, the configuration part is done for the Exception Handling block, which can be used throughout the application level.
 
Let’s build a sample console application to experience the functionality.
 
ExceptionHandler Class 
  1. using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling;  
  2. using Microsoft.Practices.EnterpriseLibrary.Logging;  
  3. using System;  
  4.   
  5. namespace ExceptionHandlingBlock  
  6. {  
  7.     /// <summary>  
  8.     /// Purpose for this type is to ease the handling of the exception handling.  
  9.     /// </summary>  
  10.     public static class ExceptionHandler  
  11.     {  
  12.         #region Static Variables  
  13.   
  14.         private static LogWriter logWriter;  
  15.         private static readonly ExceptionPolicyFactory _exceptionPolicyFactory;  
  16.         private static readonly ExceptionManager _exceptionManager;          
  17.  
  18.         #endregion  
  19.  
  20.         #region Constructor  
  21.   
  22.         static ExceptionHandler()  
  23.         {  
  24.             logWriter = new LogWriterFactory().Create();  
  25.             Logger.SetLogWriter(logWriter, false);  
  26.   
  27.             _exceptionPolicyFactory = new ExceptionPolicyFactory();  
  28.             _exceptionManager = _exceptionPolicyFactory.CreateManager();              
  29.         }  
  30.  
  31.         #endregion  
  32.  
  33.         #region Static Methods  
  34.   
  35.         /// <summary>  
  36.         /// Performs the handling of an application towards the configured policy.         
  37.         /// <param name="ex">Exception to handle.</param>  
  38.         public static void HandleException(Exception ex)  
  39.         {  
  40.             Exception exceptionToThrow = null;  
  41.   
  42.             //The HandleException method will return true if the exception should be (re-)thrown.  
  43.             if (_exceptionManager.HandleException(ex, "ExceptionHandling", out exceptionToThrow))  
  44.             {  
  45.                 if (exceptionToThrow == null)  
  46.                 {  
  47.                     Console.WriteLine(ex.Message);  
  48.                     Console.ReadKey();  
  49.                 }  
  50.                 else  
  51.                 {  
  52.                     Console.WriteLine(exceptionToThrow.Message);  
  53.                     Console.ReadKey();  
  54.                 }  
  55.             }  
  56.         }   
  57.  
  58.         #endregion  
  59.     }  
  60. }  
Executer Class
  1. using System;  
  2. using System.IO;  
  3.   
  4. namespace ExceptionHandlingBlock  
  5. {  
  6.     class Executer  
  7.     {  
  8.         static void Main(string[] args)  
  9.         {  
  10.             BaseException();  
  11.   
  12.             //DivideByZeroException();  
  13.   
  14.             //FileNotFoundException();  
  15.         }  
  16.   
  17.         public static void BaseException()  
  18.         {  
  19.             try  
  20.             {  
  21.                 string x = null;  
  22.                 int a = 10;  
  23.   
  24.                 Console.WriteLine(int.Parse(x) + a);  
  25.             }  
  26.             catch (Exception ex)  
  27.             {  
  28.                 ExceptionHandler.HandleException(ex);  
  29.             }  
  30.         }  
  31.   
  32.         public static void DivideByZeroException()  
  33.         {  
  34.             try  
  35.             {  
  36.                 int x = 5;  
  37.                 int y = 0;  
  38.                 int z = x / y;  
  39.             }  
  40.             catch (DivideByZeroException ex)  
  41.             {  
  42.                 ExceptionHandler.HandleException(ex);  
  43.             }  
  44.         }  
  45.   
  46.         public static void FileNotFoundException()  
  47.         {  
  48.             try  
  49.             {  
  50.                 // Read in non-existent file.  
  51.                 using (StreamReader reader = new StreamReader("TextFile1.txt"))  
  52.                 {  
  53.                     reader.ReadToEnd();  
  54.                 }  
  55.             }  
  56.             catch (FileNotFoundException ex)  
  57.             {  
  58.                 ExceptionHandler.HandleException(ex);  
  59.             }  
  60.         }          
  61.     }  
  62. }  
Let me explain a bit about the above code blocks.
  • The ExceptionHandler class will handle the exceptions for all types of exceptions as we have defined here DivideByZeroException, FileNotFoundException, and the base Exception class will deal with the remaining exceptions.
  • The ExceptionHandler class will also log the messages for each exception occurred in the application.
  • The Executer class contains three methods to test the various exception handlers that we have configured in the application.
Once you execute the application, it will create the Log file in the debug folder as no specific path is mentioned for the file in the configuration and log the message in Windows Event Log.
 
.net
 
Executing the BaseException Method
  • As we know, it will throw an ArgumentNullException, but as we are not handling this in our configuration, it will come under Base Exception Handler which uses WrapHandler.
  • We can see in the below log message it wrapped the exception with our custom message in the configuration as “Exception occurred in application”
     
    .net
Windows Event Log
 
.net
 
Executing the DivideByZeroException Method
  • As we know, it will throw a DivideByZeroException and we are handling it in our configuration, it will come under DivideByZero Exception Handler, which uses ReplaceHandler.
     
  • We can see in the below log message it replaced the exception with our custom message in the configuration as “Divide By Zero Exception Occurred”, whereas the actual message should have been “Attempted to divide by zero”.
     
    .net
Windows Event Log
 
.net
 
Executing the FileNotFoundException Method
  • As we know, it will throw a FileNotFoundException and we are handling it in our configuration, it will come under FileNotFound Exception Handler, which uses ReplaceHandler.
     
  • We can see in the below log message it replaced the exception with our custom message in the configuration as “FileNotFound Exception Occurred”, whereas the actual message should have been “Could not find file 'C:\Users\FCOXG6Z\Desktop\Projects\ExceptionHandlingBlock\ExceptionHandlingBlock\bin\Debug\TextFile1.txt'.
     
    .net
Windows Event Log
 
.net
 

Conclusion

 
The best part of the Exception Handling Application block is that you can change policies and handlers on the fly without compiling the code. You can also change the error logging source from event viewer to file or email. I have attached the sample application. Just download it and experience the Exception Handling functionality in Microsoft Enterprise Library 6.0.
 
I hope you have enjoyed this article and I am sure if you use this block properly, you can have a very stable, efficient, and flexible error handling framework.
 
In the next article, we will cover the Data Access Application Block in Microsoft Enterprise Library 6.0.
 
Happy Coding!!!


Similar Articles