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)
2 answers
Sort by: Most helpful
-
-
SurferOnWww 2,246 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.