Creating your own Unhandled Error Logging Module

I'm a big fan of the ELMAH project which I utilise in my personal website
This is great for plugging into an existing website to catch unhandled exceptions, but not ideal when you want to log to an existing infrastructure.
So I set of on the task to create my own custom unhandled error logging module, and this is what I came up with.

HttpApplication contains various information that can be really useful when finding bugs or reviewing errors.
This can be nicely broken down into 5 categories:

  • Exception Information
  • Server Variables
  • QueryString Variables
  • Form Variables
  • Cookie Variables

Exception Information
This is available using the HttpApplication.Server.GetLastError() method.
This returns a System.Exception.

Server Variables
This contains a stacks of useful information. This includes info like: HTTP_REFERER, HTTP_USER_AGENT, PATH_INFO, REMOTE_ADDR and several other useful items to help trace the cause of the exception.
This is obtained from the HttpApplication.Context.Request.ServerVariables NameValue collection.

QueryString Variables
This will contain your querystring information.
This is obtained from the HttpApplication.Context.Request.QueryString NameValue collection.

Form Variables
This will contain any form information like that posted to the page that threw the exception.
This is obtained from the HttpApplication.Context.Request.Forms NameValue collection.

Cookie Variables
This will read any cookie information stored by your website.
This is obtained from the HttpApplication.Context.Request.Cookies HttpCookieCollection.

Now we can create a module to catch an unhandled exception, and gather all this information.
We start by creating a class that inherits from the interface IHttpModule.
In our Init method, we assign a delegate to our Error event of our HttpApplication context.

public class ErrorHandler : IHttpModule
   public void Init(HttpApplication context)
      context.Error += Context_Error;

Simple as that, any unhandled exception that occurs in our application, will be caught by our Context_Error event. Lovely!
Now let's setup our Context_Error void. Here we can gather all our information we need, and use it as we see fit

public void Context_Error(object sender, EventArgs e)
   //Cast sender to a HttpApplication
   HttpApplication app = (HttpApplication)sender;

   //Get the exception that occurred
   Exception ex = app.Server.GetLastError();

   //Get Querystring Variables
   NameValueCollection queryStringVariables = app.Context.Request.QueryString;

   //Get Form Variables
   NameValueCollection formVariables = app.Context.Request.Form;

   //Get Cookie Collection
   HttpCookieCollection cookieCollection = app.Context.Request.Cookies;

   //Get Server Variables
   NameValueCollection serverVariables = app.Context.Request.ServerVariables;


Now you can use this information to log away anything you need to help you troubleshoot the problem.
2 more methods which may help you loop through a NameValueCollection or a HttpCookieCollection

//Loop through a name value collection
private static void AddNameValueCollection(NameValueCollection nvc)
   if (nvc == null || nvc.Count == 0) return;
   if (nvc.HasKeys())
   foreach (string key in nvc.Keys)
      //Get all your name values with 'key' and 'nvc[key]'

//Loop through an HttpCookieCollection
private static void AddCookieCollection(HttpCookieCollection cookies)
   if (cookies == null || cookies.Count == 0) return;
   for (var i = 0; i < cookies.Count; i++)
      var cookie = cookies[i];
      //Get all your name values with 'cookie.Name' & 'cookie.Value'

Now you have bucket loads of information to look through in the event of an unhandled exception occurring in your website or web application!

posted @ Wednesday, September 17, 2008 4:12 PM