ASP.NET MVC 5 CancellationToken fix

Hey everyone!

I got a neat little fix for you.

Problem: CancellationToken not being cancelled upon request abort.

We stumbled upon this small bug whilst implementing a straight foward, basic MVC 5 application.
My co-worker pointed out that the following code, although valid and correct was not working as expected in MVC 5:


[Route("tools/test")]
[HttpGet]
public async Task Test(CancellationToken token)
{
	var now = DateTime.Now;

	while (DateTime.Now < now.AddMinutes(1))
	{
		if (token.IsCancellationRequested)
		{
			return Json(false);
		}

		await BotherGoogle(token).ConfigureAwait(false);
	}

	return Json(true);
}

private async Task BotherGoogle( CancellationToken token)
{
	using (var httpClient = new HttpClient())
	{
		await httpClient.GetAsync("http://www.google.be", token).ConfigureAwait(false);
	}
}

I would call this action from JavaScript and abort the XHR request on the client after 5 seconds:


function startTest() {
	var xhr = $.get('@Url.Action("Test")', function(data) {
		toastr.info(data);
	});
	toastr.info('Test started');

	setTimeout(function() {
		xhr.abort();
		toastr.info('Test aborted');
	}, 5000);
}

As soon as the request had been aborted on the client, it would take around +- 40 seconds before the cancellation token on the server was marked as cancelled.

A solution

A solution, pointed out by Muhammad Rehan Saeed on David Paquette’s blog here involved linking 2 cancellation tokens together so if one cancellation token gets cancelled, so would the linked ones:

Continue reading ASP.NET MVC 5 CancellationToken fix