简体   繁体   中英

Web API filters not catching exceptions thrown from a method group

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);
}

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM