我编写了以下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();
}
}
说,我想取消请求,所以值'true'记录在上面的控制器动作中。如果服务器实现了IHttpRequestLifetimeFeature,这在服务器端是可能的。幸运的是,红隼做到了,这可以通过以下方式完成:
var feature = (IHttpRequestLifetimeFeature) HttpContext.Features[typeof(IHttpRequestLifetimeFeature)];
feature.Abort();
问题是我想在客户端取消请求。例如,在浏览器中。在pre-core版本的ASP。如果浏览器终止请求,取消令牌将自动取消。示例:在Chrome中刷新页面几次。在chrome开发工具的网络选项卡中,您现在可以看到先前(未完成)的请求被取消。
问题是:在ASP中。. NET Core在Kestrel上运行时,我只能在日志中看到以下条目:
Microsoft.AspNetCore.Server.Kestrel.Internal.Networking.UvException:错误-4081取消操作取消
因此,来自浏览器的abort请求确实到达并由Kestrel web服务器处理。但是,它不会影响控制器中HttpContext的requestablished属性,因为值'false'仍然被该方法记录。
问题:是否有一种方法来中止/取消我的控制器的方法,以便HttpContext。请求建立的属性将被标记为已取消?
也许我可以做一些东西,将订阅红隼的操作取消触发器和调用IHttpRequestLifetimeFeature.Abort()方法?
更新:我做了一些进一步的测试,似乎HttpRequest IS实际上中止了,但在取消实际发生之前似乎有某种延迟。延迟不是时间因素,并且似乎直接来自libuv (Kestrel web服务器构建在其上的库)。我在https://github.com/aspnet/KestrelHttpServer/issues/1103上发布了更多信息
更多更新:Issue已经转移到另一个,因为前一个包含多个问题。https://github.com/aspnet/KestrelHttpServer/issues/1139
事实证明,只需使用HttpContext。requestablished确实是正确的方式,但是由于Kestrel中的一个bug(处理FIN/RST包的顺序),请求在浏览器abort时没有被中止。
这个错误应该最终在Kestrel 2.0中修复。
请参阅我的问题中的更新以获取更多信息。