Web API 过滤器未捕获从方法组抛出的异常

Web API filters not catching exceptions thrown from a method group

我正在使用 WebApi。我的基本控制器上有一个自定义 ActionFilter,全局添加了一个自定义 ExceptionFilter。两者都是从 System.Web.Http.Filters 命名空间中关联的 FilterAttributes 继承的,而不是 mvc 版本。

我的一项服务中的私有方法抛出了一个异常,当它在 Linq 语句中使用时,resharper 将此方法称为方法组(在本例中为 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");
}

此异常未被任一过滤器捕获(请参阅下面的过滤器)。我的操作过滤器说没有异常,我的异常过滤器从未被命中。如果我在 Linq select(我已经注释掉的那个)之前抛出一个异常,那么这个异常就会按预期被捕获。

使用fiddler,我得到的结果是:

{  
   "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":""
   }
}

我的动作过滤器的一部分:

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

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

和我的异常过滤器的一部分:

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

    _loggedErrorService.Log(actionExecutedContext.Exception);
}

来自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[...]

问题是,如果您从您的 WebAPI 方法 return 一个 IEnumerable<T>,则在序列化期间,当迭代 IEnumerable<T> 时,会发生错误。这是 Select(以及大多数其他查询运算符)的标准行为,它仅在迭代时调用传递给它的方法(在本例中为 MakeFooFromBar),因此当您调用 Select 但很久以后。

您可以添加一个 .ToList 以导致异常在您的方法中发生。