In my application I am creating a ZipArchive that writes directly to the ASP.Net Core body stream, like that:
```C#
using var zipArchive = new ZipArchive(Response.Body, ZipArchiveMode.Create, true);
Asynchronously writing file contents to that archive works fine, but as soon as the writing is finished and the `ZipArchive` gets disposed, the `ZipArchive` tries to synchronously write some more data to the stream. This results in an exception, because Kestrel, by default, doesn't allow synchronous writes anymore:
```C#
System.InvalidOperationException: Synchronous operations are disallowed. Call WriteAsync or set AllowSynchronousIO to true instead.
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpResponseStream.Write(Byte[] buffer, Int32 offset, Int32 count)
at Microsoft.AspNetCore.ResponseCompression.ResponseCompressionBody.Write(Byte[] buffer, Int32 offset, Int32 count)
at System.IO.Compression.PositionPreservingWriteOnlyStreamWrapper.Write(Byte[] buffer, Int32 offset, Int32 count)
at System.IO.BinaryWriter.Write(UInt32 value)
at System.IO.Compression.ZipArchiveEntry.WriteCentralDirectoryFileHeader()
at System.IO.Compression.ZipArchive.WriteFile()
at System.IO.Compression.ZipArchive.Dispose(Boolean disposing)
at System.IO.Compression.ZipArchive.Dispose()
Enabling async disposal for this class and then doing the necessary writes asynchronously would probably resolve this issue.
looks like duplicate of https://github.com/dotnet/corefx/issues/5681
Does it work if you use FlushAsync before disposing? There is no flush API...
Triage:
@vtchalkov the ZipFile issue is not a duplicate.
This looks like a legitimate scenario. Next step would be to add a PR to implement it and add DisposeAsync.
This needs first to add async methods to BinaryWriter via dotnet/corefx#8382
Test running successfully with https://github.com/manandre/runtime/pull/1 馃憤
[Fact]
public static async Task DiposeAsyncCallsWriteAsyncOnly()
{
MemoryStream ms = new MemoryStream();
CallTrackingStream trackingStream = new CallTrackingStream(ms);
await using (ZipArchive archive = new ZipArchive(trackingStream, ZipArchiveMode.Create))
{
archive.CreateEntry("hey");
}
Assert.Equal(0, trackingStream.TimesCalled("Write"));
Assert.NotEqual(0, trackingStream.TimesCalled("WriteAsync"));
}
Most helpful comment
Test running successfully with https://github.com/manandre/runtime/pull/1 馃憤