Should we use CancellationToken with MVC/Web API controllers?
Solution 1
You should use it. Right now it only applies if you have an AsyncTimeout
, but it's likely that a future MVC/WebAPI version will interpret the token as "either timeout or the client disconnected".
Solution 2
You could use this
public async Task<ActionResult> MyReallySlowReport(CancellationToken cancellationToken)
{
CancellationToken disconnectedToken = Response.ClientDisconnectedToken;
using (var source = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, disconnectedToken))
{
IEnumerable<ReportItem> items;
using (ApplicationDbContext context = new ApplicationDbContext())
{
items = await context.ReportItems.ToArrayAsync(source.Token);
}
return View(items);
}
}
taken from here.
Solution 3
Users can cancel requests to your web app at any point, by hitting the stop or reload button on your browser. Typically, your app will continue to generate a response anyway, even though Kestrel won't send it to the user. If you have a long running action method, then you may want to detect when a request is cancelled, and stop execution.
You can do this by injecting a CancellationToken into your action method, which will be automatically bound to the HttpContext.RequestAborted token for the request. You can check this token for cancellation as usual, and pass it to any asynchronous methods that support it. If the request is cancelled, an OperationCanceledException or TaskCanceledException will be thrown.
Below link explains this scenario in detail.
https://andrewlock.net/using-cancellationtokens-in-asp-net-core-mvc-controllers/
user1224129
Updated on August 04, 2020Comments
-
user1224129 almost 4 years
There are different examples for async controllers. Some of them use CancellationToken in method definition:
public async Task<ActionResult> ShowItem(int id, CancellationToken cancellationToken) { await Database.GetItem(id, cancellationToken); ...
But other examples and even the default ASP.NET projects for VS2013 don't use CancellationToken at all and work without it:
public async Task<ActionResult> ShowItem(int id) { await Database.GetItem(id); ...
It's not clear, if we should use CancellationToken in controllers or not (and why).
-
Drew Noakes about 9 yearsHas the situation with Web API changed with respect to cancellation tokens and disconnected clients?
-
Stephen Cleary about 9 years@DrewNoakes: AFAIK it has not yet. I believe this will be fixed in ASP.NET vNext.
-
Jonathan Allen almost 9 yearsI just tested it under VS 2015 and hitting stop in the browser did trigger the cancellation token.
-
eesh over 8 yearsHow would you pass a Cancellation Token from a C# Web Client to a Get API method? How do you serialize the cancellation token into the URL string?
-
Stephen Cleary over 8 years@eesh: I wouldn't try that at all. Instead, consider having the client close its connection when a cancellation token is triggered; and having the server take a cancellation token as an argument (which is automatically supplied by WebAPI and canceled when the connection is dropped).
-
Miles over 6 yearsYou MUST dispose LinkedTokenSource because it will never be collected by GC and it will cause memory leak. MSDN: Notice that you must call Dispose on the linked token source when you are done with it. msdn.microsoft.com/en-us/library/dd997364.aspx
-
Leonid Vasilev over 6 yearsIn this case cancellation token behavior depends on framework version and server implementation. See CancellationToken issue in ASP.NET MVC GitHub repository.
-
Tomas Kubes almost 5 yearsI tested it (F5, Esc) on React App and it works with Firefox and it does not work with Chrome and Edge.
-
SeanStanden over 4 yearsAccording to the reference, this process is required to make the cancellation token work with MVC 5; "...for some reason, MVC 5 only supports cancellation if you use the AsyncTimeout attribute.". The article points out that "Everything works as expected in both ASP.NET Core MVC and in Web API...". i.e. If you're using .NET Core then you need only pass the CancellationToken through as normal.
-
Triynko almost 4 yearsSo Chrome and Edge are incorrectly keeping the connection to the server open AFTER the tab/window is closed?
-
Stephen Cleary almost 4 years@Triynko: I'm not sure why that would be incorrect behavior, assuming HTTP 1.1 or newer.
-
jenson-button-event over 3 yearsand ajax requests in SPAs?