jjaskulowski
jjaskulowski

Reputation: 2564

What happens when connection is lost during execution of action in controller?

Imagine we're calling REST APIs inside our action, all of them changing state of something, and in-between these lines, connection from client is ended.

Imaging we're loading some huge chunk of data from storage to return it as a stream (I know bad practice), and inside this line connection ends.

Finally, imaging we're returning a stream with a 1GB movie from our action which (the stream) handles all the reading and returning inside, and the connection is lost.

What happens?

Will we have exception thrown? Will we have all the code executed and result pushed to dev/null?

Upvotes: 0

Views: 573

Answers (2)

pfx
pfx

Reputation: 23274

As @StriplingWarrior describes, within your controllers action method, it's up to check the IsCancellationRequested property of the passed in CancellationToken and to decide what kind of result to return.

When a client disconnects while already writing to the output stream an OperationCanceledException will be thrown. This occurs outside of the controller, within a FileResult-derived class, e.g. FileContentResult.

The source code of ASP.NET Core handling the streaming/writing of a file to the output stream, deals with this by catching this exception and aborting the connection.

Notice the comments in the original source code.

internal static async Task WriteFileAsync(HttpContext context, Stream fileStream, RangeItemHeaderValue? range, long rangeLength)
{
    // ...      
    using (fileStream)
    {
        try
        {
            // ...
        }
        catch (OperationCanceledException)
        {
            // Don't throw this exception, it's most likely caused by the client disconnecting.
            // However, if it was cancelled for any other reason we need to prevent empty responses.
            context.Abort();
        }
    }
}

Upvotes: 1

StriplingWarrior
StriplingWarrior

Reputation: 156624

When the connection from the client ends, the cancellation token associated with the request will get invoked. If you take a CancellationToken as an argument to your action, you can use it to detect this and cancel the action in whatever way you deem appropriate for your use case. Otherwise your action will continue to execute as if nothing had happened.

Typically the controller action returns a "Result" object that knows how to handle sending data to the client. In a streaming scenario, your result would be an object that streams data to the client. This happens outside the lifetime of the controller action (after the action has returned). If a connection dies (either to the client or from the source) while the streaming result is in progress, an exception gets thrown. I don't recall more details. Hopefully someone else can provide a more complete answer.

Upvotes: 3

Related Questions