Search code examples
blazorblazor-client-side

Getting HTTP stream is blocking rendering


I'm downloading a stream from a WebAPI and I'm trying to run code while the stream is being read.

The code below works fine on Blazor server-side or an console app. But on blazor-client side the stream will first download fully before executing any code.... even just a Console.WriteLine() will just start writing to Console after the stream is done. I'm using the latest .Net Core 3.0 Preview 8...

public async IAsyncEnumerable<SomeClass> GetDataAsync()
{
    var serializer = new JsonSerializer();
    using (var stream = await Http.GetStreamAsync("https://localhost:44334/api/values/i"))
    {
        using (var sr = new StreamReader(stream))
        using (var jr = new JsonTextReader(sr))
        {
            while (await jr.ReadAsync()) //<-- Stream is fully download to browser before taking any actions.
            {
                if (jr.TokenType != JsonToken.StartArray && jr.TokenType != JsonToken.EndArray)
                {
                    Console.WriteLine(jsonReader.LinePosition);
                    yield return serializer.Deserialize<SomeClass>(jr);
                }
            };
        }
    }
}

I tested this with WireShark to confirm that this is happening.

Is this by design?


Solution

  • Is this by design?

    I guess it is currently by design !

    this will not block simply because the async / await pattern is supported in client-side Blazor. It seems to me that the real issue is with HttpClient.GetStreamAsync, as the HttpClient service (client-side Blazor) is not the actual or real HttpClient. It is based on the JavaScript Fetch Api (https://github.com/aspnet/AspNetCore/blob/master/src/Components/Web.JS/src/Services/Http.ts):

    responseData = await response.arrayBuffer(); 
    

    But if they switch to the mono implementation (https://github.com/aspnet/AspNetCore/issues/10489), streaming will be support if the browser supports it: https://github.com/mono/mono/blob/254d6d37580a70fbb4fa072b0b2b16d2984b3bb5/sdks/wasm/framework/src/WebAssembly.Net.Http/WasmHttpMessageHandler.cs#L171-L173

    A call to arrayBuffer() will never return from a pure stream. A different MessageHandler based on this example would have to be implemented, but I'm pretty sure it's not enough to just implement a new message handler in this case.

    Hope this helps...