HttpRequest在ASP.NET Core MVC中没有中止(取消)浏览器中止

时间:2016-09-19 13:10:21

标签: asp.net-core asp.net-core-mvc cancellation kestrel-http-server

我编写了以下MVC控制器来测试取消功能:

class MyController : Controller
{
    [HttpGet("api/CancelTest")]
    async Task<IActionResult> Get()
    {
        await Task.Delay(1000);
        CancellationToken token = HttpContext.RequestAborted;
        bool cancelled = token.IsCancellationRequested;
        logger.LogDebug(cancelled.ToString());
        return Ok();
    }
}

说,我想取消请求,因此值&#39; true &#39;记录在上面的控制器操作中。如果服务器实现IHttpRequestLifetimeFeature,这可能是服务器端。幸运的是,Kestrel确实如此,这可以通过以下方式实现:

var feature = (IHttpRequestLifetimeFeature) HttpContext.Features[typeof(IHttpRequestLifetimeFeature)];
feature.Abort();

但问题是我想取消客户端的请求。例如,在浏览器中。在ASP.NET MVC / WebApi的预核版本中,如果浏览器中止请求,则取消令牌将自动取消。示例:在Chrome中多次刷新页面。在chrome dev工具的“网络”选项卡中,您现在可以看到上一个(未完成的)请求被取消。

问题是:在Kestrel上运行的ASP.NET Core中,我只能在日志中看到以下条目:

  

Microsoft.AspNetCore.Server.Kestrel.Internal.Networking.UvException:   错误-4081 ECANCELED操作已取消

因此来自浏览器的中止请求到达并由Kestrel网络服务器处理。但它不会影响控制器中HttpContext的RequestAborted属性,因为值&#39; false &#39;仍然按方法记录。

问题: 有没有办法中止/取消我的控制器的方法,以便HttpContext.RequestAborted属性将被标记为已取消?

也许我可以制作一些可以订阅Kestrel操作取消触发器并调用IHttpRequestLifetimeFeature.Abort()方法的东西?

更新 我做了一些进一步的测试,似乎HttpRequest IS 实际上已经中止了,但在实际取消之前似乎有某种延迟。延迟不是时间因素,似乎直接来自libuv(Kestrel网络服务器构建在其上的库)。我在https://github.com/aspnet/KestrelHttpServer/issues/1103

上发布了更多信息

更多更新: 问题已转移到另一个问题,因为前一个问题包含多个问题。 https://github.com/aspnet/KestrelHttpServer/issues/1139

1 个答案:

答案 0 :(得分:3)

事实证明,简单地使用HttpContext.RequestAborted确实是正确的方法,但是由于Kestrel中的错误(处理FIN / RST包的顺序),请求在浏览器中止时没有中止。

最终应该在Kestrel 2.0中修复错误。

有关详细信息,请参阅我的问题中的更新。