Introduction
Error handling is one of the more difficult tasks any developer or development team must implement. Teams face all sorts of challenges on how to handle exceptions within applications. Oftentimes, you end up "re-creating the wheel" for every application you design; since many believe that the application's provisions dictate the exception-handling methodology, you end up needing to recreate exception handling for each application you develop.
Microsoft has provided you with a large method of exception management with their Exception Application Block, but for many application scenarios, this block may be too large. Though it provides many degrees of flexibility, it can be cumbersome to set up and configure, and in a lot of cases, even larger than the application you're developing!
This article will present a far simpler approach, and provide you with a flexible library you can use to handle your own exceptions. The ErrorTrapper
library is completely self-contained within a single .NET assembly, and is relatively flexible to use via specifying information in your App.config or Web.config file. First, the design of the ErrorTrapper
will be discussed in short detail. Then, a sample scenario will be presented using WinForms technology which will demonstrate a relatively basic implementation of the ErrorTrapper
's usefulness.
First things first - the IErrorReporter interface
The main component of the ErrorTrapper
library - the part which will yield flexibility in the design of the model itself - is the IErrorTrapper
. Below, you can see the C# code which provides this interface's structure:
public interface IErrorReporter
{
bool ReportError(Exception exception);
}
Classes which implement this interface need only contain implementation for the single method ReportError()
. Your own classes can provide whatever implementation you need for the application, using the ErrorTrapper
library. In a moment, we'll take a look at using late binding and the Activator.CreateInstance()
method to create instances of types which can implement this functionality.
The code download provided with this article contains a simple WinForms application which utilizes the ErrorTrapper
library. This implementation simply writes the ToString()
equivalent of the handled exception to a file on disk. Below, you can see the code for this class and get an idea of how flexible the ErrorTrapper
library can be in your own application development cycles:
public class CustomErrorTrapperExample : IErrorReporter
{
public bool ReportError(Exception exception)
{
try
{
string filename = @"C:\ExceptionLog.txt";
FileMode fm = FileMode.Append;
if(!File.Exists(filename))
{
fm = FileMode.Create;
}
StringBuilder sb = new StringBuilder();
FileStream fs = new FileStream(filename,fm);
sb.Append(DateTime.Now.ToString());
sb.Append(Environment.NewLine);
sb.Append("---------------------------------------------------------");
sb.Append(Environment.NewLine);
sb.Append(exception.ToString());
sb.Append(Environment.NewLine);
sb.Append("---------------------------------------------------------");
sb.Append(Environment.NewLine);
string s = sb.ToString();
Byte[] byt = Encoding.ASCII.GetBytes(s);
fs.Write(byt,0,byt.Length);
fs.Close();
return true;
}
catch
{
return false;
}
}
Though this is a relatively simple example, it demonstrates how you can, in your own application paradigm, write custom implementations that the ErrorTrapper
library will execute whenever applications "explode".
So how can I make it flexible?
The answer to this question is relatively simple. Using a custom configuration section in your app.config or web.config file, you'll provide some information that "drives" certain aspects of the ErrorTrapper
library. As you'll see in a moment, there is a user interface aspect to the ErrorTrapper. For now, let's save that discussion and take a look at the configuration code that provides information to the library at runtime.
="1.0" ="utf-8"
<configuration>
<configSections>
<section name="ErrorTrapper"
type="System.Configuration.NameValueSectionHandler" />
</configSections>
<ErrorTrapper>
<add key="exceptionHandlerType"
value="ClientApplication.CustomErrorTrapperExample,
ClientApplication"/>
<add key="showUI" value="true"/>
<add key="uiLabel" value="Something Exploded!"/>
<add key="uiIntro"
value="We're sorry, but something has happened.
Would you like to report this explosion?"/>
</ErrorTrapper>
</configuration>
As you can see from this configuration section, we're going to use a relatively simple paradigm for configuring the ErrorTrapper
library. By using the NameValueSectionHandler
configuration class, we'll provide four properties that the ErrorTrapper
will need to use at runtime:
exceptionHandlerType
(string
)
showUI
(bool
)
uiLabel
(string
)
uiIntro
(string
)
The first of these properties, exceptionHandlerType
, will be the name of a Type
that the ErrorTrapper
will create at run-time to handle exceptions. One caveat is important to note here - the Type
provided in this area must implement the IErrorReporter
interface! If it does not, an exception will be thrown at runtime (makes sense if you think about it!). The class we discussed earlier with the simple implementation - CustomErrorTrapperExample - has been provided in this example.
Now - the WinForms interface!
Microsoft Windows and some of the supporting applications provide us with an awesome feature - the ability to send errors as they occur to a Microsoft Web Service which tallies up the exceptions that happen in their applications. You've seen the dialog that pops up from time to time when certain programs "explode", providing you the option of reporting the error to Microsoft.
Well, the ErrorTrapper
library provides something very similar for your WinForms applications - a user interface that displays the exception's information, with a "Send" and "Don't Send" button your users can use as they wish. The dialog displayed by this implementation is below:
Now that you've got a reference, we'll continue the examination of the final three configuration elements. The first of these, a Boolean property called showUI
, can be used to specify whether the UI is displayed or not. Think about it this way - if you want to use the ErrorTrapper
in a WebForms application, it wouldn't be a good idea to display this UI. If this value is set to true
, the user has the option of submitting the exception to your custom IErrorReporter
implementation. If the value is set to false
, your implementation simply executes.
Next is the uiLabel
property. In the example screenshot, this value has been set to the string "Something Exploded!". Simply, this element/property defines the dialog's Text
property, and is displayed in the title bar of the WinForm when it is shown.
Finally, the uiIntro
property. Pretty simply, this is the text which is displayed to the user above the buttons. As you can see from this example, you can customize not only the functionality that happens when exceptions are handled by the ErrorTrapper
library - you can even customize the dialog that's displayed to users when exceptions are handled in a WinForms application! Total flexibility!
Finally, Using the ErrorTrapper
The last piece of code we'll take a look at is from the sample download. This WinForms user interface provides two buttons that fire - or cause - simple exceptions. At the beginning of the application's execution, we'll simply handle the ThreadException
event, and within the event handler, send the exception that is fired into the ErrorTrapper
's execution cycle. The code for this is below:
static void Main()
{
Application.ThreadException += new
System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
Application.Run(new Form1());
}
private static void Application_ThreadException(object sender,
System.Threading.ThreadExceptionEventArgs e)
{
ErrorHandler.HandleError(e.Exception);
}
private void btnSimpleError_Click(object sender, System.EventArgs e)
{
throw new Exception("This is a simple error");
}
private void btnDbFailure_Click(object sender, System.EventArgs e)
{
SqlConnection cn = new SqlConnection("this will break");
cn.Open();
}
And that's about it! Here you have a simple, flexible, and totally customizable exception management tool, complete with a Windows XP-like user interface that can be displayed to your users should you want to provide them the option of reporting or not reporting exceptions as they occur!
Happy coding!
Note - this assembly has already been strong-named and documented for you. So feel free to drop it into your GAC and use it wherever you need!