Tuesday, 23 September 2008

Microsoft Enterprise Library #2 – Exception Application Block

This is the second in a series of blogs looking at the Enterprise Library for development. In the last session I looked at the logging block, this session I'm going to look at the Exception block. There is no coincidence about the order that I'm doing these in, the Exception block has an optional dependency to the logging block that I'm going to exploit for the purposes of filling my requirements of the Exception block. For this blog post I'll be re-using some of the setup from the previous post for this reason.

My Requirements

My requirements for exception handling are far more simple than my logging requirements. I want to:

  1. Log all exceptions to the event log
  2. Email security exceptions to an email address
  3. Rethrow database exceptions to the application to handle at a higher level (so the user will see them)

Step 1 - Logging to the Event Log

I'm going to re-use my logging block for this, previously I've setup that all error type logs go into the event log. The easy way to use this is to just associate the base exception with the error logging mechanism. Firstly I'll add a new Exception Handling Application block to my config file. I'll add a new Exception Policy to that, and as I'm only going to have a single policy for this project I'll leave the default name. This is the base that I'll work from for this example. I want to log all exceptions, in .NET every exception inherits from Exception, so I'll add a new exception type and choose System.Exception. After this is added I'll right click the new Exception type and add a new Logging Handler. In my logging handler I'll choose the LogCategory of Error, which I previously setup in the Logging Application Block and a FormatterType of TextFormatter as the event log is in text. Your App.config should look something like this:

 

Now we need to add some code to show how to use the exception. I'll add a new reference to

  • Microsoft.Practices.EnterpriseLibrary.ExceptionHandling
  • Microsoft.Parctices.EnterpriseLibrary.ExceptionHandling.Logging
(you'll need to browse to the DLL file to do so) and add a using to my code. Then I'll write some code to throw an exception, catch it and send it to the exception handler.
public static void TestExceptionHandling()
{
 Console.WriteLine("Exception handling starting");

 try
 {
  throw new System.Exception("Testing exception!");
 }
 catch (System.Exception Ex)
 {
  try
  {
   if (ExceptionPolicy.HandleException(Ex,
    "Exception Policy"))
   {
    throw;
   }
  }
  catch (Exception ExNew)
  {
   Console.WriteLine("Exception caught: " +
   ExNew.Message);
  }
 }

 Console.WriteLine("Exception handling finished");
 Console.ReadLine();
}

Now when I run this code my exception handler is going to use the error logging facility that I've already setup and log to the event log. It will also log to the log file because I've told the system to log everything to the log file as well. How easy was that?

Step 2 - Emailing Security Exceptions

I want to email security exceptions to someone becuase we need to be sure that we investigate these exceptions straight away. I've already setup warnings to be emailed to a user, this security exception sounds like it fits in this category so I'll re-use the warning log type the same as before. I don't want to use any of the custom exceptions so I'm going to create my own, I'll call it CustomSecurityException. Make sure you make it public because otherwise the enterprise library won't be able to see it. Here is the code for the custom exception.

public class CustomSecurityException : System.Exception
{
}

And as you can see it does nothing, it's just for example. Now we'll add a new handler for this type. Right click the policy, add a new type. You'll need to load an assembly, I selected my .exe file where the public exception class resides and it added my namespace and exception class to the selectable types. I selected my custom exception and then added a logging handler as before, this time selecting the Warning log category. Something to note, I've been told that the library is only loaded once into enterprise library configuraiton tool, if your objects are not there try restarting the environment and trying again. I didn't have this problem however. After running the application I get an email in my inbox specifying the exception details and the log format wrapper around it.

Step 3 - Rethrowing Database Exceptions

The last thing I want to do with my exception handling environment is have the ability to rethrow new exceptions after processing. This time I'm just going to catch a System.Data.DataException. It pays to know the object heirarchy for exceptions when handling exceptions. As before I add the System.Data.DataException type and this time I set it to "ThrowNewException" in the PostHandlingAction property. From here I added a Replace Handler to the DataException type and set the ReplaceExceptionType to System.Exception (select it from the list). I don't want the user seeing the exception so I put my own validation message ino there. It should look something like this:

Now when I write some code to throw the a Data Exception all I need to do is pass through an output exception to rethrow like so;

try
{
System.Exception newException;

if (ExceptionPolicy.HandleException(Ex,
"Exception Policy", out newException))
{
throw newException;
}
}
catch (System.Exception ExNew)
{
Console.WriteLine("Exception caught: " + ExNew.Message);
}

The rethrown exception shows the message in the screenshot above written out to the console.

Final Thoughts

Adding exception handling policies to your application is remarkably simple, even if it's something as simple as logging them to the event log you can be sure that every handled exception is picked up and handled. I can think of many real work examples in the past where I would have found this tool remarkably useful and I hope to find places for it in the future. One thing I did not investigate in this blog, and may have a look at next time, is creating a bunch of custom handlers for exceptions. This allows you to use your code structure to handle your exceptions when they happen and the exception block to catch and direct them.

No comments: