异常处理 ASP.NET MVC Web API

Posted

技术标签:

【中文标题】异常处理 ASP.NET MVC Web API【英文标题】:Exception Handling ASP.NET MVC Web API 【发布时间】:2012-05-04 07:28:36 【问题描述】:

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

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

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

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

我们可以做些什么来处理之前的错误,ASP.NET MVC Web API 代码似乎受到了什么影响?

【问题讨论】:

这感觉有点不对劲。您是否在某处的库中抛出异常?为什么不直接在控制器中捕获异常并返回您自己选择的错误视图? 这是使用 ASP.NET MVC Web API,所以我们不会从控制器返回视图。我们返回 JSON/XML 响应。我还在我的问题中提到,我需要一种在异常到达控制器之前处理异常的方法。现在我们有一个 ExceptionFilter,一旦我们进入控制器,它就会在任何地方捕获异常,因此我们不必在每个操作中都有 try/catch。 我认为我没有完全理解您的问题。您要准确捕获哪些类型的错误? @cecilphillip 例如,如果有人使用错误的 JSON 格式访问服务并且 API 找不到它的格式化程序。或者当只有一个 POST 时,有人点击了一个试图使用 GET 的控制器,它会发回一个 405。在它到达控制器之前发生的事情,这就是过滤器的用途。这几乎就像在 ControllerDispatcher 或某种内置处理程序中引发了异常。我在配置中插入了一个自定义 DelegatingHandler 以查看返回的响应。我可以看到在调试器中返回的 InternalServerError 消息,但不是异常。 【参考方案1】:

尽管我喜欢 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状态码,并尽力给消费者一个合理或可能的答案。

【讨论】:

如果任何人都在寻找有关将呼叫连接到config.MessageHandlers.Insert() 的文档,可以使用in the WebAPI documentation。 如果您想在 Web API 中使用具有完整异常信息的全局错误处理程序,请在 aspnetwebstack.codeplex.com/workitem/1001 投票支持此功能 这看起来也很方便:blog.codeishard.net/2013/02/09/…

以上是关于异常处理 ASP.NET MVC Web API的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Web API模型验证以及异常处理方式

ASP.NET Web API 处理异常返回错误状态码

七天学会ASP.NET MVC ——线程问题异常处理自定义URL

在 ASP.NET Web Api 中捕获所有未处理的异常

ASP.NET Web API、405 状态码和异常处理

基于.Net Framework 4.0 Web API开发:ASP.NET Web APIs 异常的统一处理Attribute 和统一写Log 的Attribute的实现