12

Using an API controller in MVC4, when the controller action throws an exception, ELMAH does not log the error.

I think the problem is that MVC4 sets the HTTP status code to 500, and it returns the exception details in a JSON object, but it does not throw an unhandled exception so ELMAH never sees it.

How can I get ELMAH to capture all responses where the status code is not 200?

tereško
  • 58,060
  • 25
  • 98
  • 150
Greg Ennis
  • 14,917
  • 2
  • 69
  • 74
  • 3
    It's probably worth noting that API controllers are in Web API, not MVC. The separate execution paths for each is often the cause of incompatibility of an MVC-targeted library with Web API. Each request either goes MVC, or it goes Web API. The two are side-by-side and don't interact (Web API is not a feature inside MVC execution). They have different contexts, different route tables, different configs, all different, all separate. – StarTrekRedneck Jul 30 '13 at 15:32

2 Answers2

22

The anwser described before doesn't work. I've tried on my test server and received an error ("The given filter instance must implement one or more of the following filter interfaces: IAuthorizationFilter, IActionFilter, IResultFilter, IExceptionFilter.")

Then I realized what happened .... you are trying to add the custom filter to the MVC Global Filter (filters.Add(new ElmahHandledErrorLoggerFilter());)

To fix that, I've split the filter registration in GlobalFilter and HttpFilter

FilterConfig.cs

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
    }

    public static void RegisterHttpFilters(HttpFilterCollection filters)
    {
        filters.Add(new ElmahHandledErrorLoggerFilter());
    }

Global.asax

    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    FilterConfig.RegisterHttpFilters(GlobalConfiguration.Configuration.Filters);

;-)

julianox
  • 758
  • 1
  • 7
  • 9
  • 2
    With the current scaffolding of Web API the filter should be registered in App_Start/WebApiConfig.cs. config.Filters.Add(new ElmahExceptionFilter()); – Josh C Mar 28 '13 at 18:49
  • I just installed via nuget Elmah.MVC. super easy to get going, but, not logging 500 errors. I understand the answer above, but, don't see the ElmahHandledErrorLoggerFilter (shown in the code snippet above) in my Elmah.* or Elmah.Mvc.* spaces EDIT: oops, I see now.. it's a class that you write yourself.. and it's shown in O.P.'s code snippet. Sorry! ;) – bkwdesign Jun 13 '13 at 20:28
  • Hi. This works and error gets logged to elmah, but no mail is being sent for all api 500s. What could be the solution to this ? – Yasser Shaikh Jun 16 '14 at 11:36
16

UPDATE: This answer does not work in latest versions. Use julianox's answer.

Answer found from information here: http://www.asp.net/web-api/overview/web-api-routing-and-actions/exception-handling

Where the exception filter logs to elmah:

public class ElmahHandledErrorLoggerFilter : ExceptionFilterAttribute
{
    public override void OnException(HttpActionExecutedContext actionExecutedContext)
    {
        base.OnException(actionExecutedContext);

        ErrorSignal.FromCurrentContext().Raise(actionExecutedContext.Exception);
    }
}

but you also have to add the error filter to the GlobalConfiguration filters:

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        GlobalConfiguration.Configuration.Filters.Add(new ElmahHandledErrorLoggerFilter());
        filters.Add(new ElmahHandledErrorLoggerFilter());
        filters.Add(new HandleErrorAttribute());
    }
Greg Ennis
  • 14,917
  • 2
  • 69
  • 74
  • Great stuff. I struggled with this and hadn't added the Elmah filter to the GlobalConfiguration. – Magnus Johansson Jun 28 '12 at 07:47
  • 1
    When I did this, it didn't work at all unless I added the GlobalConfiguration.Configuration.Filters.Add(new ElmahHandledErrorLoggerFilter()); in the RegisterGlobalFilters method. Shouldn't the filters.Add(new ElmahHandledErrorLoggerFilter()); line have done it? What's the point of having both? – JustinP8 Aug 17 '12 at 15:46
  • @JustinP8 WebApi has almost completely recreated some of the things that were already in MVC. Although this is frustrating you can see that WebApi and MVC are different characters - one UI orientated the other software orientated. If you check out the types returned by GlobalConfiguration.Configuration.Filters (HttpFilterCollection) and GlobalFilters.Filters (GlobalFilterCollection) you can see they are different beasts. – WooWaaBob Feb 22 '13 at 16:19
  • This does not worked for me. I got this error `The given filter instance must implement one or more of the following filter interfaces: IAuthorizationFilter, IActionFilter, IResultFilter, IExceptionFilter.` The other answer above (http://stackoverflow.com/a/13264550/1182982) worked for me. – Yasser Shaikh May 05 '14 at 11:42