ASP.NET Web API and ELMAH Integration

See how ASP.NET Web API Plays Nice With ELMAH. This blog post is a Quick introduction to ASP.NET Web API and System.Web.Http.Filters.IExceptionFilter
2012-02-23 13:53
Tugberk Ugurlu


As you all probably heard, ASP.NET MVC 4 Beta is now available and has new features in it. One of them is that ASP.NET MVC has shipped with ASP.NET Web API (which was previously know as WCF Web API). Here is the quote from ASP.NET web site which explains what Web API Framework is all about shortly:

ASP.NET Web API is a framework that makes it easy to build HTTP services that reach a broad range of clients, including browsers and mobile devices. ASP.NET Web API is an ideal platform for building RESTful applications on the .NET Framework.

I am not going to give an into on ASP.NET Web API. There are great into tutorials and videos on ASP.NET web site for ASP.NET Web API. Instead, I will give you an example of a custom filter implementation.

A couple of months ago, I wrote a blog post about WCF Web API HttpErrorHandlers: WCF Web API Plays Nice With ELMAH - A Quick Introduction to WCF Web API HttpErrorHandler. It works nicely on WCF Web API but this version of the framework, things a little bit changed. Instead of ErrorHandlers, we now have Filters which is more generic.

In order to make ELMAH work with ASP.NET Web API, we need to create a new Attribute which implements IExceptionFilter interface. Since we have ExceptionFilterAttribute (which implements the IExceptionFilter interface) available at the framework, we will derived from that class instead. Here is the whole implementation:

public class ElmahErrorAttribute : 
    System.Web.Http.Filters.ExceptionFilterAttribute {

    public override void OnException(
        System.Web.Http.Filters.HttpActionExecutedContext actionExecutedContext) {

        if(actionExecutedContext.Exception != null)
            Elmah.ErrorSignal.FromCurrentContext().Raise(actionExecutedContext.Exception);

        base.OnException(actionExecutedContext);
    }
}

Now we have our attribute, we need to tell the framework to use it. It is very straight forward as well. Here is how my Global.asax (Global.asax.cs) looks like:

public class WebApiApplication : System.Web.HttpApplication {

    protected void Application_Start() {

        Configure(
            System.Web.Http.GlobalConfiguration.Configuration
        );
    }

    private void Configure(HttpConfiguration httpConfiguration) {

        httpConfiguration.Filters.Add(
            new ElmahErrorAttribute()
        );

        httpConfiguration.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

This will make Elmah log the errors. Now, you can configure ELMAH to send you an e-mail when an error occurred or you can log the error inside an XML file, SQL Server Database, wherever you what.

One more thing to mention about is that when you hit an error, the response will carry the exception details at the body of the response if you run your application locally. You can configure this option as well with the following configuration:

httpConfiguration.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Never;


Comments

Antony Scott
by Antony Scott on Monday, Mar 12 2012 16:36:29 +02:00

It doesn't seem to work for me. I've put some defensive code in there to stop it hiding the actual exception with it's own.

        public override void OnException(HttpActionExecutedContext actionExecutedContext)
        {
            if (actionExecutedContext.Exception != null)
            {
                var context = ErrorSignal.FromCurrentContext();
                if (context !=  null)
                {
                    context.Raise(actionExecutedContext.Exception);
                }
            }
            base.OnException(actionExecutedContext);
        }

It seems that HttpContext is referred to directly within elmah, which I believe isn't populated by the Web Api. Have you experienced any issues using this attribute?

Aaron Coleman
by Aaron Coleman on Saturday, Mar 31 2012 00:46:41 +03:00

Works great for me, thanks! I applied it at the controller class level, perfect!

--Aaron

Mariano Korman
by Mariano Korman on Tuesday, Aug 07 2012 09:29:01 +03:00

I experience the same issue as Anthony Scott.

I'm using a self-hosted WebApi. It looks like there is no HttpContext there. Even HttpContext.Current returns null.

My guess is that HttpContext only exists within an IIS-hosted application.

Self-hosted WebAPI seems to use HttpActionContext and HttpControllerContext instead.

Unless I am missing some configuration which is not mentioned in this article.

Thanks!

Tugberk
by Tugberk on Tuesday, Aug 07 2012 15:27:05 +03:00

@Mariano

No, u are right. Other than the ASP.NET host, they don't have the HttpContext. So, this can only work with apps hosted on IIS. I was being sloppy when writing this post apperently and didn't think about that :) I'll probably update later.

Ando
by Ando on Monday, Oct 22 2012 18:20:23 +03:00

Tugberk-

I am having a problem with getting Elmah to catch Web API errors. The solution uses a plugin-style interface, where the main project acts as a gateway and contains all the relevant routing information and error-handling and suchlike. The actual controllers and views are in separate projects (under the same solution). 

I have copied your overridden class exactly, but whenever a Web API controller throws an exception, Elmah does not catch and log it. Breakpoints set in the ElmahErrorAttribute class do not get hit.

So does setting the filter globally (using global.asax, as in your example) only work in whatever project the attribute is defined in? Or am I missing something?

Thanks!

Hrusi
by Hrusi on Tuesday, Nov 27 2012 16:52:16 +02:00

For those who are having issues getting the global filters configuration to work, take a look here: http://stackoverflow.com/a/13264550/244353

 

 

steel erection
by steel erection on Friday, Dec 20 2013 16:19:25 +02:00
You've really helped me understand the issues. Thanks.
Anoop
by Anoop on Wednesday, Apr 02 2014 17:14:13 +00:00
How can we get the elmah logs to work, when it is self hosted and is being accessed from a console application? Here @Mariano seems to suggest that, it will now work. Can you please suggest ?

Tags