Web API filters not catching exceptions thrown from a method group

1.6k views Asked by At

I'm using WebApi. I have a custom ActionFilter on my base controller and a custom ExceptionFilter added globally. Both are inherited from the associated FilterAttributes in the System.Web.Http.Filters namespace, not the mvc versions.

I've been getting an exception thrown from a private method within one of my services, this method is what resharper calls a method group, when it's used within a Linq statement (in this case a select).

public IEnumerable<Foo> GetFoos()
{
    IEnumerable<Bar> bars = _work.BarRepository.GetAll();

    //throw new Exception("I'm visible to the filters");

    IEnumerable<Foo> foos = bars.Select(MakeFooFromBar);

    return foos;
}

private Foo MakeFooFromBar(Bar bar)
{
    // an exception is being thrown here
    // which is not being caught by the filers
    throw new Exception("I am invisible to the filters");
}

This exception is not being caught by either filter (see filters below). My action filter says there was no exception and my exception filter is never hit. If I throw an exception prior to the Linq select (the one I've commented out), then the exception is caught as expected.

Using fiddler, what I end up with is this:

{  
   "message":"An error has occurred.",
   "exceptionMessage":"The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'.",
   "exceptionType":"System.InvalidOperationException",
   "stackTrace":null,
   "innerException":{  
      "message":"An error has occurred.",
      "exceptionMessage":"I am invisible to the filters",
      "exceptionType":"System.Exception",
      "stackTrace":""
   }
}

A portion of my action filter:

public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
    Exception exception = actionExecutedContext.Exception;

    if (exception == null)
    {
        // do things
    }
    else
    {
        // do some other things
    }
}

and a portion of my exception filter:

public override void OnException(HttpActionExecutedContext actionExecutedContext)
{
    // return early on certain kinds of exceptions...

    _loggedErrorService.Log(actionExecutedContext.Exception);
}
1

There are 1 answers

3
Titian Cernicova-Dragomir On BEST ANSWER

From the documentation

You can customize how Web API handles exceptions by writing an exception filter. An exception filter is executed when a controller method throws any unhandled exception[...]

The problem is that if you return an IEnumerable<T> from your WebAPI method, the error will occur during serialization, when the IEnumerable<T> is iterated. This is the standard behavior of Select (and most other query operators) it only call the method passed to it upon iteration (MakeFooFromBar in this case), so the exception will not be thrown when you invoke Select but much later.

You could add a .ToList to cause the exception to occur inside your method.