the main issue is that with http protocol, it is a request/response protocol with no cancel support. the server typically will not detect a closed socket until it sends a response. this does not help with a long running query. you can change to websocket or signal/r where you could add support for sending a cancel event on the same connection as the query request, and process cancel.
Cancellation Token signal not being received by the application code
looks like there is a limitation as it can be read here
https://github.com/dotnet/aspnetcore/issues/20229#issuecomment-623289191
https://learn.microsoft.com/en-us/answers/questions/391343/cancellationtoken-in-controller-endpoint-hosted-in
but is there anything that can be done? our api needs to cancel a long running query if the user for example navigates to another page or just abort the request from one of the api client (SPA)
4 answers
Sort by: Most helpful
-
-
SurferOnWww 3,276 Reputation points
2024-06-22T01:16:34.5866667+00:00 If your app is hosted by IIS with in-process hosting model the following article might help:
Handling aborted requests in ASP.NET Core
The IIS in-process hosting model means:
Please read the following document:
Differences between in-process and out-of-process hosting
"The following characteristics apply when hosting in-process: Client disconnects are detected. The HttpContext.RequestAborted cancellation token is cancelled when the client disconnects."
Cancellation by client includes (1) click X button on the browser, (2) depress Esc key on keyboard, or (3) abort when XMLHttpRequest is used:
Sample code:
View
@{ ViewData["Title"] = "Cancel"; Layout = "~/Views/Shared/_Layout.cshtml"; } <h1>Cancel</h1> <input type="button" id="ajaxRequest" value="Ajax Request" /> <br /> <input type="button" id="abortButton" value="Abort" /> <br /> <div id="result"></div> @section Scripts { <script type="text/javascript"> //<![CDATA[ var xhr; $(function () { $('#ajaxRequest').on('click', function (e) { xhr = $.ajax({ url: '/home/cancel', method: 'get', }).done(function (response) { $("#result").empty; $("#result").text(response); }).fail(function (jqXHR, textStatus, errorThrown) { $("#result").empty; $("#result").text('textStatus: ' + textStatus + ', errorThrown: ' + errorThrown); }); }); $('#abortButton').on('click', function (e) { if (xhr) { xhr.abort(); } }); }); //]]> </script> }
Controller / Action Method
using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using MvcCore5App4.Models; using System.Diagnostics; using Microsoft.AspNetCore.Authorization; using System.Threading; using System.Threading.Tasks; using System; using Microsoft.AspNetCore.Identity; using MvcCore5App4.Data; namespace MvcCore5App4.Controllers { public class HomeController : Controller { private readonly ILogger<HomeController> _logger; public HomeController(ILogger<HomeController> logger) { _logger = logger; } // ・・・中略・・・ public async Task<IActionResult> Cancel(CancellationToken token) { _logger.LogInformation($"start: {DateTime.Now:ss.fff}"); await Task.Delay(5000, token); _logger.LogInformation($"end: {DateTime.Now:ss.fff}"); return View(); } } }
Result of [Start Debugging] the above code shown on the Output of Visual Studio 2022:
See "Start again - Cancelled" in which a client cancelled within 5 sec.
-
ajkuma 26,721 Reputation points Microsoft Employee
2024-06-24T18:57:23.3466667+00:00 @Michel Fornaris , Based on my understanding of the scenario - The Linux workers run Kestrel/YARP which does forward request cancellation. If your requirement fits, you may test your scenario on a Linux app.
We have a Uservoice feedback: HttpRequest cannot be cancelled: HttpContext.RequestAborted CancellationToken doesn't work in Azure environment
Checkout these article/blogs: A Heavy Lift: Bringing Kestrel + YARP to Azure App Services | A Heavy Lift: Bringing Kestrel + YARP to Azure App Services
If the answer helped (pointed you in the right direction) > please click Accept Answer
-
Bruce (SqlWork.com) 67,016 Reputation points
2024-06-27T22:00:06.9433333+00:00 triggering the cancelation token is unreliable. see the protocol:
https://en.wikipedia.org/wiki/Transmission_Control_Protocol#Connection_termination
in the http protocol, there is no defined support for request cancel other than do it gracefully (preferable wait for response end). The implementation is left to each server and client.
in azure you are accessing the website via several proxy servers. azure has firewall servers, routing servers, frontend balancing servers, and often the client side has its own firewall servers and routing servers. each of these servers have their own logic for handling an http request cancel. any one of these proxies can fail to pass the cancel to the actual webserver. as noted above, even running out of process in IIS loses the cancel.
so to reliabily do what you want, you will need to change your code, and use websockets rather than http.