3

I have an API with .net core 2.1 and use cancellation tokens in actions. When i run the project with iis and make a simple request in browser, after i cancel it, it doesn't work as expected and run all methods with cancellation token passed to them. But when i run the project using the kestrel server, cancelling the request causes the server to work as expected. why is that?

    [HttpGet("get")]
    public async Task<IActionResult> GetSome(CancellationToken ct)
    {

        _logger.LogInformation("The slow Request Start");
        try
        {
            await Task.Delay(10_000, ct);
            _logger.LogCritical("Successful");
        }
        catch (Exception)
        {
            _logger.LogInformation("Task Cancelled");
        }
        var message = "The request finished";

        _logger.LogInformation(message);

        return NoContent();
    }
  • From my limited understanding of request cancellation, it is the job of the web server hosting your application to tell your application that a request has been cancelled, i.e, if your web server doesnt have this functionality, even if your code is right, it simply wont trigger the task cancellation via your CancellationToken. Kestrel supports this functionality, whilst IIS im not so sure. Hope someone with more detailed knowledge on the topic can shed more light. – Gerald Chifanzwa Oct 29 '18 at 11:58
  • Possible duplicate of [Can't cancel task in Asp.net core Action](https://stackoverflow.com/questions/50702303/cant-cancel-task-in-asp-net-core-action) – Kirk Larkin Oct 29 '18 at 12:13
  • `make a simple request in browser, after i cancel it` there's no such thing. The HTTP request isn't cancelled - it can't be cancelled. You only tell the browser to stop waiting for a response and possibly close the TCP connection – Panagiotis Kanavos Oct 29 '18 at 13:43
  • 1
    There are proper ways to start or cancel long running jobs. For one thing, they *shouldn't* be implemented as long-running actions. Use eg a HostedService instead. As for monitoring, cancellation, one option is to return a token to the client when the job is started, and use it to poll for progress or request cancellation. You may want to add HangFire to your application if there are many long running jobs, as it supports scheduling, progress reporting, cancellation etc – Panagiotis Kanavos Oct 29 '18 at 13:50

1 Answers1

7

Right now, this isn't possible when hosting ASP.NET Core up to 2.1 in (or more specific behind) IIS, the cancellation or connection loss won't be passed down to the ASP.NET Core application.

Right now it only works when hosting/exposing directly through Kestrel or HTTP.SYS (formerly known as Weblistener).

With ASP.NET Core 2.2 (from preview3 and later), the AspNetCoreModule has been updated to support this feature. However, its limited to IIS inprocess hosting and won't work when IIS acts as a mere reverse proxy.

See the ASP.NET Core 2.2-preview3 Announcement blog.

We added support for the ability to detect client disconnects when you’re using the new IIS in-process hosting model. The HttpContext.RequestAborted cancellation token now gets tripped when your client disconnnects.

However, be aware that while in-process adds improved performance and less overhead, it also means that you can only have one application per App Pool hosted as in-process, if I remember correctly.

Tseng
  • 61,549
  • 15
  • 193
  • 205
  • Client disconnect isn't the same thing as "cancelling" a client request. An HTTP request can't be cancelled. Detecting a client disconnect may be the best way to handle a … misbehaving client though – Panagiotis Kanavos Oct 29 '18 at 13:44
  • That's exactly what [HttpContext.RequestAborted](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.http.httpcontext.requestaborted?view=aspnetcore-2.1) property on HttpContext is supposed to do: _Notifies when the connection underlying this request is aborted and thus request operations should be cancelled_ Kestrel is capable of doing that, but when the ASP.NET Core app is hosted in IIS, that won't be passed down to the application itself (probably its not closing the tcp connection from iis to the app for performance reasons? I dunno) – Tseng Oct 29 '18 at 15:39
  • @PanagiotisKanavos: Unlike traditional ASP.NET applications, ASP.NET Core has always been hosted as out-of-process application and IIS merely acting as reverse proxy, redirecting the requests to the ASP.NET Core application. With ASP.NET Core 2.2 it becomes possible to host ASP.NET Core in-process too (with some limitations – Tseng Oct 29 '18 at 15:41