Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clarification on how IAsyncEnumerable works with ASP.NET Web API

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?

like image 426
Ravi M Patel Avatar asked Nov 15 '19 12:11

Ravi M Patel


People also ask

How does IAsyncEnumerable work?

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.

Is ASP Net Web API is cross platform?

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.

How does API work in asp net?

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.

How do I content negotiation in Web API?

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.


1 Answers

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:
enter image description here

After ~5 seconds:
enter image description here

After ~10 seconds:
enter image description here


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: (...)

like image 186
tymtam Avatar answered Sep 17 '22 12:09

tymtam