Search code examples
c#asp.net-core.net-8.0

HttpContext.RequestAborted not canceled when Android APP loses connection


I currently have a .NET 8 ASP.NET Core application running on my PC through Kestrel and an .NET for Android APP running on my physical device.

From the mobile app i'm trying to upload a large file (~70 MB) to a controller using streaming (for more information see this: https://learn.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads?view=aspnetcore-8.0#upload-large-files-with-streaming) and simulate a lost connection (i'm simulating this by disabling the wi-fi on the physical device).

The problem is, the cancellation token exposed by HttpContext.RequestAborted does not get cancelled making the file created locked on filesystem. The code running is the following:

await using var fileStream = IOFile.Create(filePath, bufferSize: 1024);

await fileSection.FileStream?.CopyToAsync(fileStream, HttpContext.RequestAborted);

Note: The problem is present ONLY when trying through the mobile APP, when making the same test from Postman on the same machine the ASP.NET Core application is running the cancellation token gets cancelled.

Does anyone know why the token does not get cancelled? If yes: is there a solution?

Thank you in advance.


Solution

  • i'm simulating this by disabling the wi-fi on the physical device)

    This is not reliable client-side cancellation behavior.

    What happens if the mobile client enters a no-network area while the file is being uploaded?

    Periodically, the server sends keepalive probes to check if the peer is still responding. If the peer does not respond to these keepalive probes within a predetermined amount of time, the system considers the connection to be lost. The TCP keepalive interval and number of retries are usually configurable, but the default can cause a disconnect to be detected for minutes to hours after the client loses connectivity.

    Reliable solution

    The server should add a timeout mechanism to the upload operation, after which the server will automatically cancel the task and process the uploaded resources.

    var cancellationTokenSource = new CancellationTokenSource();
    // Set a timeout period, for example, 60 seconds
    cancellationTokenSource.CancelAfter(TimeSpan.FromSeconds(60));
    
    try
    {
        await using var fileStream = IOFile.Create(filePath, bufferSize: 1024);
        // A linked CancellationToken is used here, which is canceled when the RequestAborted or timeout
        var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationTokenSource.Token, HttpContext.RequestAborted);
    
        await fileSection.FileStream?.CopyToAsync(fileStream, linkedTokenSource.Token);
    }
    catch (OperationCanceledException)
    {
        //  Handle cancellations, such as deleting or saving partially uploaded files
    }