Reputation: 2564
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
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
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