【问题标题】:Exception handling beyond Exception Filters?异常过滤器之外的异常处理?
【发布时间】:2012-07-13 15:59:47
【问题描述】:

使用 Asp.net WebApi (RC),我如何捕捉 global.asax 中 Exception FiltersApplication_Error() 未捕捉到的错误?

有了这两个,似乎还有一类例外仍未涵盖。例如:ApiControllerActionSelector_AmbiguousMatch 错误 (Multiple actions were found that match the request: {0})。

我并不特别关心上述错误,这个错误只是指出有一类错误没有被我的异常过滤器或Application_Error 方法捕获。

那么我怎样才能覆盖我所有的基地呢?

【问题讨论】:

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


    【解决方案1】:

    你是对的,有几类异常没有被 Application_Error 或 ExceptionFilter 捕获。 Web API 请求管道与 ASP.NET MVC 管道分开处理(至少通过 MVC 4),因此 MVC Application_Error 不会启动。此外,如果您的应用程序抛出 HttpResponseException 类型的异常,它们不会ExceptionFilter by design 捕获(参见 ExceptionFilter 段落)。要访问您的代码引发的所有异常,您需要按照以下代码行创建DelegatingHandler

    public class ResponseExceptionTrapper : DelegatingHandler
    {
        protected override Task<HttpResponseMessage> SendAsync(
            HttpRequestMessage request,
            CancellationToken cancellationToken)
        {
            return base
                .SendAsync(request, cancellationToken)
                .ContinueWith(response =>
                     {
                         var result = response.Result;
                         if (!result.IsSuccessStatusCode)
                         {
                              var exceptionResult = string.Format(
                                   "Response exception: Path({0}) Status({1}) ",
                                   request.RequestUri,
                                   result.StatusCode);
    
                              if (result.Content != null)
                              {
                                   var exceptionReadTask =
                                          result.Content.ReadAsStringAsync();
    
                                   exceptionReadTask.Wait();
                                   exceptionResult += "Message:\n\r" +
                                                     exceptionReadTask.Result;
                               }
    
                               // Do something appropriate with exceptionResult
                          }
    
                          return result;
                     }, cancellationToken);
        }
    }
    

    您可以在全局配置逻辑中使用此行连接处理程序:

    GlobalConfiguration.Configuration.MessageHandlers.Add(
         new ResponseExceptionTrapper());
    

    【讨论】:

      【解决方案2】:

      我相信只有在调用操作后才会调用异常过滤器(在这种情况下,它周围有一个 try/catch)。歧义匹配错误会在此之前在管道中弹出,之后可能会弹出其他错误(例如格式化程序错误),正如您所提到的。

      我不确定您是否可以使用一种解决方案来解决所有方面的问题(因为托管实现可能会有所不同),但您可以尝试覆盖 HttpControllerDispatcher。此类是管道中使用的“根”类之一。具体来说,您可以覆盖 SendAsync 来执行您的 try/catch 并相应地进行处理。

      【讨论】:

      • 我同意关于异常过滤器在管道中的位置的评估。我只是对 Application_Error 没有启动感到惊讶。我并不担心单一的解决方案,只要确保我的应用程序无论错误如何都能优雅地运行。我没有考虑过覆盖调度程序...这将需要一段时间才能回到这个...但我会报告。
      • 通过一系列单元测试来尝试解决这个问题可能会更容易。搜索并识别所有可用的控制器和操作非常容易,然后调用其中的每一个以查看是否返回任何异常。使用 WebApi 更容易,因为您可以进行自托管进行测试。
      • 感谢您的指点——我同意该方法。然而,单元测试只是——测试。即使您拥有 100% 的代码覆盖率,您仍然可能会错过各种各样的事情——集群故障转移、内存不足、大量锁定争用、应用程序域循环等等......
      • 这篇文章描述了HttpControllerDispatcher的用法:aspnetwebstack.codeplex.com/workitem/574
      猜你喜欢
      • 2016-06-14
      • 2013-05-03
      • 2015-07-03
      • 1970-01-01
      • 2012-06-04
      • 2021-11-12
      • 2021-05-19
      • 1970-01-01
      • 2012-01-31
      相关资源
      最近更新 更多