2

Examples exist to read data from an IAsyncEnumerator to the UI in a Blazor app using an internal service. Examples also exist on how to send an IAsyncEnumerator as an output from a Web API Controller action.

I haven't seen any examples yet how to read an IAsyncEnumerator stream from an API using an HttpClient within a client like Blazor or Xamarin. Everything I've tried so far, only returns the HttpResponseMessage on the client after the async/await foreach loop on the API is done.

HttpResponseMessage response = await _httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);

What should the content type be (Produces attribute) on the HttpGet action? What should the Accept value be on the request header from the HttpClient?

[HttpGet]
[Produces("application/json")]
public async IAsyncEnumerable<Data> Get(CancellationToken cancellationToken)
{
    var dbSet = _dbContext.TableName.AsNoTracking().AsAsyncEnumerable().WithCancellation(cancellationToken).ConfigureAwait(false);
    await foreach (var i in dbSet.ConfigureAwait(false))
    {
        var item = new Data
        {
            Id = i.Id,
            Name = i.Name
        };
        yield return item;
    }
}
WebDiddy
  • 21
  • 2
  • so you need to `response.Content.ReadAsStreamAsync()` and deserialize entities from the stream like [here](https://johnthiriet.com/efficient-api-calls/#). What is your issue? please provide a full client code. – fenixil Oct 07 '19 at 04:09
  • Blazor uses SignalR to stream changes to the client. Returning IAsyncEnumerable won't turn the action into a SignalR endpoint. The HTTP response doesn't change at all. Besides, both JSON nor XML return entire documents, not partial results - the results will still arrive at the client as a JSON array – Panagiotis Kanavos Oct 07 '19 at 07:20
  • 1
    You'll have to use SignalR or gRPC streaming if you want the client to handle streaming results. Both are available in .NET Core, easy to write and fast. – Panagiotis Kanavos Oct 07 '19 at 07:21

1 Answers1

2

You'd better not do it with raw http 1.1 request-response model, which is not designed for this, and streaming objects are different from downloading files. With websocket or http2.0 that support multiplexing, you can serialize each elements produced by the IAsyncEnumerable and deserialize them in the client. But still this is manually controlled and not worth. You could use gRPC which is officially supported by ASP.NET Core and supports object streaming. It also supports many more languages and has strongly typed interface definition in comparison with SignalR which supports JavaScript/.NET/Java only and .

sbp
  • 913
  • 8
  • 19
Alsein
  • 4,268
  • 1
  • 15
  • 35