Skip to content

Creating a ZIP is incompatible with ASP.NET asynchronous I/O #102450

Open
@branko-d

Description

@branko-d

Description

When trying construct a ZipArchive "on the fly" and serve it from the Web API, I have to turn-on the ASP.NET synchronous I/O mode, otherwise I get an exception when trying to create or write to ZIP entries. So far, I have encountered exceptions:

  • when calling Stream.WriteAsync on the stream returned from ZipArchiveEntry.Open,
  • and when calling ZipArchive.CreateEntry repeatedly (see the attached project).

Reproduction Steps

The following controller action illustrates the problem:

[HttpGet]
public async Task Get() {

    using (var zip_archive = new ZipArchive(Response.Body, ZipArchiveMode.Create, true)) {

        var zip_entry = zip_archive.CreateEntry("test.txt");

        await using (var stream = zip_entry.Open()) {
            // System.InvalidOperationException: 'Synchronous operations are disallowed. Call WriteAsync or set AllowSynchronousIO to true instead.'
            await stream.WriteAsync(Encoding.UTF8.GetBytes("Hello ZIP!"));
        }

    }

}

Here is a small project which illustrates the problem:

ZipAspAsyncIO.zip

If you access the route /zip or /zip2 you'll see the exception in the debugger and the corresponding diagnostic page in the browser.

Expected behavior

The ZIP archive is constructed and served without throwing any exceptions.

Actual behavior

The following exception is thrown:

System.InvalidOperationException: 'Synchronous operations are disallowed. Call WriteAsync or set AllowSynchronousIO to true instead.'

Regression?

No response

Known Workarounds

The exception can be avoided by setting IHttpBodyControlFeature.AllowSynchronousIO, as mentioned in aspnetcore / #7644.

That, of course, allows the ZIP code to "hog" the thread. It would be much better to upgrade the ZIP code to support true asynchronous I/O, which would benefit scalability and also remove the need for this workaround.

Configuration

.NET 8
Windows 11 Pro
x64

Other information

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions