I encountered an interesting behavior while exploring IAsyncEnumerable in an ASP.NET Web API project. Consider the following code samples:
// Code Sample 1
[HttpGet]
public async IAsyncEnumerable<int> GetAsync()
{
for (int i = 0; i < 10; i++)
{
await Task.Delay(1000);
yield return i;
}
}
// Code Sample 2
[HttpGet]
public async IAsyncEnumerable<string> GetAsync()
{
for (int i = 0; i < 10; i++)
{
await Task.Delay(1000);
yield return i.ToString();
}
}
Sample 1 (int array) returns {}
as JSON result.
Sample 2 returns expected result ["0","1","2","3","4","5","6","7","8","9"]
. However, entire JSON array is returned at once after 10 seconds of wait. Shouldn't it be returned as data becomes available as expected from IAsyncEnumerable interface? Or is there any specific way this web api should be consumed?
IAsyncEnumerable<T> exposes an enumerator that has a MoveNextAsync() method that can be awaited. This means a method that produces this result can make asynchronous calls in between yielding results. Cool! This method can now yield data asynchronously.
ASP.NET is an open source web framework, created by Microsoft, for building modern web apps and services with . NET. ASP.NET is cross platform and runs on Linux, Windows, macOS, and Docker.
The Web API returns the data on request from the client, and it can be in the format XML or JSON. The MVC architecture is the Model-View-Controller Pattern. It is used for isolating an application to simplify testing and the maintenance of the code of the application.
In Web API, content negotiation is performed by the runtime (at the server side) to determine the media type formatter to be used based to return the response for an incoming request from the client side. Content negotiation is centered on Media type and Media type formatter.
In .NET 6, about 2 years after the question was asked, it works as you expected.
[HttpGet]
public async IAsyncEnumerable<int> Get()
{
for(int i = 0; i < 10; i++)
{
await Task.Delay(TimeSpan.FromSeconds(1));
yield return i;
}
}
will result in the browser receiving partial results over time.
After ~3 seconds:
After ~5 seconds:
After ~10 seconds:
Pre .NET6
Up to .NET 6, at the time your question was asked, the web api call will not return partial json every second. It's the json serialiser who has to wait 10x1second (or the code that calls the json serialiser, which is part of ASP .NET). Once the framework code and the serialiser get all data, it will be serialised and served to the client as a single response.
In Controller action return types in ASP.NET Core web API we can read:
In ASP.NET Core 3.0 and later, returning IAsyncEnumerable from an action:
- No longer results in synchronous iteration.
- Becomes as efficient as returning IEnumerable.
ASP.NET Core 3.0 and later buffers the result of the following action before providing it to the serializer: (...)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With