WebAPI 2.2 with Elmah

I’ve been using the sample from the asp.net website to log unhandled exceptions using the IExceptionLogger interface.

using System;
using System.Net.Http;
using System.Web;
using System.Web.Http.ExceptionHandling;

namespace Elmah.Server.ExceptionHandling
{
    public class ElmahExceptionLogger : ExceptionLogger
    {
        private const string HttpContextBaseKey = "MS_HttpContext";

        public override void Log(ExceptionLoggerContext context)
        {
            // Retrieve the current HttpContext instance for this request.
            HttpContext httpContext = GetHttpContext(context.Request);

            if (httpContext == null)
            {
                return;
            }

            // Wrap the exception in an HttpUnhandledException so that ELMAH can capture the original error page.
            Exception exceptionToRaise = new HttpUnhandledException(message: null, innerException: context.Exception);

            // Send the exception to ELMAH (for logging, mailing, filtering, etc.).
            ErrorSignal signal = ErrorSignal.FromContext(httpContext);
            signal.Raise(exceptionToRaise, httpContext);
        }

        private static HttpContext GetHttpContext(HttpRequestMessage request)
        {
            HttpContextBase contextBase = GetHttpContextBase(request);

            if (contextBase == null)
            {
                return null;
            }

            return ToHttpContext(contextBase);
        }

        private static HttpContextBase GetHttpContextBase(HttpRequestMessage request)
        {
            if (request == null)
            {
                return null;
            }

            object value;

            if (!request.Properties.TryGetValue(HttpContextBaseKey, out value))
            {
                return null;
            }

            return value as HttpContextBase;
        }

        private static HttpContext ToHttpContext(HttpContextBase contextBase)
        {
            return contextBase.ApplicationInstance.Context;
        }
    }
}

I recently changed a WebAPI application to use OWIN and later found my logging stopped working. OWIN may not have been to blame but it sure looked guilty.

Debugging through, I noticed that the Properties collection of the ExceptionLoggerContext.Request didn’t contain the MS_HttpContext key. I noticed the Elmah ErrorSignal class had a static class FromCurrentContext as well as the method in use FromContext(HttpContext context) which takes in the MS_HttpContext.

internal class GlobalExceptionLogger : ExceptionLogger
    {
        private static readonly ILog Log4Net = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        public override void Log(ExceptionLoggerContext context)
        {
            Log4Net.Error(String.Format("Unhandled exception thrown in {0} for request {1}: {2}",
                                        context.Request.Method, context.Request.RequestUri, context.Exception));
        }
    }

    public class ElmahExceptionLogger : ExceptionLogger
    {
        public override void Log(ExceptionLoggerContext context)
        {
            // Wrap the exception in an HttpUnhandledException so that ELMAH can capture the original error page.
            Exception exceptionToRaise = new HttpUnhandledException(message: null, innerException: context.Exception);

            // Send the exception to ELMAH (for logging, mailing, filtering, etc.).
            ErrorSignal signal = ErrorSignal.FromCurrentContext();

            signal.Raise(exceptionToRaise);
        }
    }

The logging is now working.

2 thoughts on “WebAPI 2.2 with Elmah

  1. I am creating a simple ‘hello world’ Azure app that uses OWIN/Katana and the global exception handler is not firing. Could you extend your sample to show the Startup class, as I think I am missing something in mine that is not letting the handler grab all of the exceptions.

    Thanks.

  2. In the Startup file I have

    WebApiConfig.Register(config);

    which calls this clase:
    public static class WebApiConfig
    {
    public static void Register(HttpConfiguration config)
    {
    //other startup code
    config.Services.Add(typeof(IExceptionLogger), new ElmahExceptionLogger());
    config.Services.Replace(typeof(IExceptionHandler), new GenericTextExceptionHandler());
    }
    }

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s