【问题标题】:Web API 2 - Global Exception Handler not working with TaskCancellationWeb API 2 - 全局异常处理程序不适用于 TaskCancellation
【发布时间】:2015-09-14 13:26:54
【问题描述】:

演示问题的代码:

  • 假设 Test Thing 是一个真实的实现,例如 DB 调用。
  • documentation for Web API states 表示未处理的异常将在全局处理程序中捕获,允许您对其进行处理。
  • 如果我用 ExceptionFilter 替换 MyErrorHandler 这确实有效,除了我正在使用的代码库使用处理程序,因为错误逻辑是一个横切关注点,并且无论错误来自何处,都将是相同的。李>
  • 如果抛出的异常类型不是 TaskCancelledException,则会按预期调用处理程序。
  • 我也尝试过最新版本的 Web API (5.2.3)。
  • 唯一的解决方法是在可能引发此类异常的任何地方添加一个 try/catch 块,不用说这很痛苦,我希望避免使用该处理程序。

鉴于这不是我的代码,我讨厌称其为错误,但经过数小时的尝试后,它开始有这种感觉。

using System;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.ExceptionHandling;

namespace WebApplication3.Controllers
{
    public class TestController : ApiController
    {
        public async Task<string> Get()
        {
            var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(1));
            return await new TestThing().ExecuteAsync(cancellationTokenSource.Token);
        }
    }

    public class MyErrorHandler : ExceptionHandler
    {
        public override Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken)
        {
            throw new HttpResponseException(HttpStatusCode.InternalServerError);
        }
    }


    public class TestThing
    {
        public async Task<string> ExecuteAsync(CancellationToken cancellationToken)
        {
            // Remove this to see the problem, I don't want to add these
            // try/catch statements all over the codebase.
            try
            {
                await Task.Delay(TimeSpan.FromMinutes(1), cancellationToken);
            }
            catch (Exception ex)
            {
                throw new Exception("Failure...");
            }

            return await Task.FromResult("Testing...");
        }
    }
}

【问题讨论】:

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


【解决方案1】:

鉴于缺乏建议或答案,我使用了自定义消息处理程序。

    public class AsyncFixHandler : DelegatingHandler
    {
        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            try
            {
                return await base.SendAsync(request, cancellationToken);
            }
            catch (TaskCanceledException)
            {
                // TODO: Log the issue here
                return new HttpResponseMessage(HttpStatusCode.InternalServerError);
            }
        }
    }

这并不理想,但 try/catch 在一个地方。我正在成功地使用它作为解决方案,直到出现更好的结果。

【讨论】:

  • 感谢您的解决方法。对于像我一样希望使用全局异常处理程序和记录器的其他人,只需抛出一个新的替换异常而不是返回 HttpResponseMessage
【解决方案2】:

这似乎是老错误了,还有一些人报告问题仍然存在。我建议您在 ASP.NET Github repo 中创建一个问题,并暂时使用您的解决方法或 another one

【讨论】:

  • 感谢错误报告的链接,在我多次尝试解决/研究此问题时,我从未发现过这一点。我可以确认这在 5.2.3 中仍然是一个问题 :(
猜你喜欢
  • 2017-10-12
  • 1970-01-01
  • 2015-09-19
  • 2015-01-02
  • 1970-01-01
  • 2017-02-01
  • 2014-04-17
  • 2012-12-31
  • 2011-05-19
相关资源
最近更新 更多