WebApi v2 ExceptionHandler未调用

时间:2014-03-04 10:52:26

标签: c# asp.net-web-api

如何从未调用自定义ExceptionHandler,而是返回标准响应(不是我想要的那个)?

像这样注册

config.Services.Add(typeof(IExceptionLogger), new ElmahExceptionLogger());
config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandler());

并像这样实施

public class GlobalExceptionHandler : ExceptionHandler
{
    public override void Handle(ExceptionHandlerContext context)
    {
        context.Result = new ExceptionResponse
        {
            statusCode = context.Exception is SecurityException ? HttpStatusCode.Unauthorized : HttpStatusCode.InternalServerError,
            message = "An internal exception occurred. We'll take care of it.",
            request = context.Request
        };
    }
}

public class ExceptionResponse : IHttpActionResult
{
    public HttpStatusCode statusCode { get; set; }
    public string message { get; set; }
    public HttpRequestMessage request { get; set; }

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        var response = new HttpResponseMessage(statusCode);
        response.RequestMessage = request;
        response.Content = new StringContent(message);
        return Task.FromResult(response);
    }
}

并像这样抛出(测试)

throw new NullReferenceException("testerror");

在控制器或存储库中。

更新

我没有其他ExceptionFilter

我发现了这种行为的触发器:

给定网址

GET http://localhost:XXXXX/template/lock/someId

发送此标头,我的ExceptionHandler正常工作

Host: localhost:XXXXX

发送此标头,它不起作用,内置处理程序返回错误

Host: localhost:XXXXX
Origin: http://localhost:YYYY

这可能是CORS请求的问题(我使用带有通配符的全局WebAPI CORS包)或最终使用我的ELMAH记录器。在Azure(网站)上托管时也会发生这种情况,尽管内置错误处理程序不同。

知道如何解决这个问题吗?

2 个答案:

答案 0 :(得分:29)

原来,默认只处理最外层异常,而不是存储库类中的异常。所以下面也必须被覆盖:

public virtual bool ShouldHandle(ExceptionHandlerContext context)
{
    return context.ExceptionContext.IsOutermostCatchBlock;
}

更新1

WebAPI v2不再使用IsOutermostCatchBlock。无论如何,我的实现没有任何变化,因为ShouldHandle中的新代码仍然阻止了我的错误处理程序。所以我使用它并且我的错误处理程序被调用一次。我以这种方式捕获控制器和存储库中的错误。

public virtual bool ShouldHandle(ExceptionHandlerContext context)
{
    return true;
}

更新2

由于这个问题引起了如此多的关注,请注意当前的解决方案是@JustAMartin在下面的评论中的linked

答案 1 :(得分:7)

这里真正的罪魁祸首是在消息处理pipline中由EnableCors方法插入的CorsMessageHandler。 catch块拦截任何异常并在它到达HTTPServer try-catch块之前转换为响应,并且可以调用ExceptionHandler逻辑

m