11

首先,是的,我们已经创建并正在使用从 ExceptionFilterAttribute 继承的异常过滤器。它在我们的身份过滤器之后立即在应用程序启动时的配置中注册,并且如果我们的 API 内部某处发生错误,它几乎可以正常工作。

话虽如此,我正在寻找一种方法来处理在到达 API 之前发生的错误。

推理:我们永远不想返回 YSOD 和/或 IIS HTML 错误。我们总是希望点击自定义异常过滤器/处理程序,以便我们可以正确处理日志记录并向用户返回 JSON 响应。

截至目前,使用 Fiddler 发出请求,我可以附加到 w3wp.exe 进程并查看请求命中 global.asax 中的 Application_BeginRequest 方法。之后,它只返回一个 500 响应。它永远不会因异常而中断代码,也不会在此之后达到我的任何断点。它似乎正在返回一个 IIS 错误。我们绝不希望这种情况发生。我们需要能够捕获所有这些“低级”异常,记录它们,并返回一些对用户有意义的东西。

之前我们可以做些什么来处理错误,似乎是什么击中了 ASP.NET MVC Web API 代码?

4

1 回答 1

4

尽管我喜欢 Darin 的回答,但它在我们的案例中不起作用,因为 ASP.NET MVC Web API 框架在内部抑制/处理异常,而不是重新抛出以命中 Global.asax 中的 Application_Error 方法。我们的解决方案是这样的。

我最终创建了一个自定义 DelegatingHandler ,如下所示:

public class PrincipalHandler : DelegatingHandler
{
    protected const string PrincipalKey = "MS_UserPrincipal";
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        setAnonymousPrincipal();

        request = InitializeIdentity(request);

        return base.SendAsync(request, cancellationToken)
            .ContinueWith(r =>
                              {
                                  // inspect result for status code and handle accordingly
                                  return r.Result;
                              });
    }
}

然后我将它插入到 HttpConfiguration 中以确保它是第一个/最后一个被命中的处理程序。处理程序在 Web API 中的工作方式是分层的。因此,每个请求要命中的第一个处理程序将是响应命中的最后一个处理程序。至少这是我的理解,如果我错了,请随时纠正我。

public static void ConfigureApis(HttpConfiguration config)
{
    config.MessageHandlers.Insert(0, new PrincipalHandler());
}

通过使用这种方法,我们现在可以检查从 Web API 和控制器的任何响应中返回的每个结果。这使我们能够处理由于某些内容未按预期返回而可能需要发生的任何日志记录。我们现在还可以更改返回的响应内容,以便 IIS 在看到某些 HTTP 状态代码时不会插入任何默认的 HTML 错误页面。

我唯一遇到的问题是,我希望他们在即将发布的 Web API 版本中对其进行更改,即他们没有在从 base.SendAsync() 返回的任务上发送异常备份。所以我们唯一需要通过的信息就是HTTP状态码,并尽力给消费者一个合理或可能的答案。

于 2012-04-24T13:30:27.977 回答