Search code examples
c#.net-core

In a C# / .NET Core web application, is it alright to use controller actions without a default value for CancellationToken?


I often find the below CancellationToken patterns withing .NET Core web application controllers (sometimes both within the same one). I would prefer using a single one for consistency.

Is there a difference when using either of these?

Pattern #1 , ct = default

[Route("my-controller")]
[ApiController]
public class MyController : ControllerBase
{
    [HttpPost("search")]
    public async Task<MyData[]> ByQuery([FromBody] query, CancellationToken ct = default)
    { 
       // ...
    }
}

Pattern #2 no default:

[HttpPost("search")]
public async Task<MyData[]> ByQuery([FromBody] query, CancellationToken ct)
{ 
    // ...
}

Both patterns seem to work as expected.


Solution

  • The slight point is here, who creates the CancellationToken for the actions?

    The answer is webserver which is Kestrel by default, when it wants to instantiate the HttpContext.

    No matter where you call the API, from a Browser or Postman, the CancellationToken will be created by Kestrel, and it makes sense because when you refresh the browser or close it, the webserver is the first one that notifies request disconnection and will fire the CancellationToken.

    So to answer your question, both scenarios will have the same CancellationToken.

    I prefer to use HttpContext.RequestAborted and no need to inject CancelltionToken in every Action and your code will be more clean:

    [HttpPost("search")]
    public async Task<MyData[]> ByQuery([FromBody] query)
    { 
       await SomeAsync(query, HttpContext.RequestAborted)
       //...
    }