I am trying to write directly to Response.Body in an ASP.NET Core 6 controller method since this is more performant in some cases.
Why do await using and using behave differently in the following code?
[Route("api/[Controller]/[Action]")]
public class TestController : ControllerBase
{
[HttpGet]
[Produces("text/plain")]
public async Task GetPlainText()
{
// No `using`: it works
// Add `using` to the following line and the response will be empty
// Add `await using` to the following line and it will work
var sw = new StreamWriter(Response.Body, leaveOpen: true);
await sw.WriteAsync("Some normal text");
await sw.FlushAsync();
}
}
Edit
Whether or not using var sw = new StreamWriter(...) works seems to depend on the HTTP client used. If Chrome is used, there is an error in the console and no text is displayed. If Postman is used, there is no error and the response contains "Some normal text".
CodePudding user response:
Not 100% sure but I would say it is because the the stream is disposed after the method completes but before the task to write and flush the stream was actually run because all that was returned was the promise to do those things.
The reason it works without the using is because dispose is never called.
The reason it works with the await using is because the disposal of the stream is also included as part of the task.
As to why the client makes a difference it could be because it is streamed to one and executed directly to the other.
CodePudding user response:
I really should have looked at the console output from ASP.NET Core, which contained this stack trace:
System.InvalidOperationException: Synchronous operations are disallowed. Call WriteAsync or set AllowSynchronousIO to true instead.
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpResponseStream.Flush()
at System.IO.StreamWriter.Flush(Boolean flushStream, Boolean flushEncoder)
at System.IO.StreamWriter.Dispose(Boolean disposing)
at System.IO.TextWriter.Dispose()
So the issue is that StreamWriter.Dispose synchronously flushes the underlying stream, and synchronous write operations are not allowed by default.
