Stream HTTP Response Content in ASP.NET Core Web API

How to stream an the HTTP response in .NET Core WebAPI

Stream HTTP Response Content in ASP.NET Core Web API
.NET Web API HTTP Stream Response

UPDATE: Article continued with part 2, advanced HTTP Streaming:

Stream HTTP Response Content in ASP.NET Core Web API - Part 2, infinite ♾️ data stream


So I came upon this issue these days.

Couldn't find a spot-on response anywhere on the web. It's either not well documented or not very well indexed because neither StackOverflow or MSDN or Google where of any help.

Any post I found was either suggesting PushStreamContent, which was available up until .NET Core 2.2, or IAsyncEnumerable which is not an option if you're using .NET Standard 2.0.

So what to do? The solution was surprisingly easy!

Return a Stream:

[Route(nameof(StreamSomethig)), HttpGet]
public Task<Stream> StreamSomethig()
{
    Response.ContentType = "application/json; charset=utf-8";
    return useCase.GenerateStream();
}

[...]

using H.Necessaire;

public async Task<Stream> GenerateStream()
{
    using(IDisposableEnumerable<MyData> dataStream = await manager.StreamData())
    {
        return await dataStream.ToJsonUTF8Stream();
    }
}

[...]

using H.Necessaire;
using H.Necessaire.Serialization;

public static async Task<Stream> ToJsonUTF8Stream<T>(this IEnumerable<T> collection)
{
    MemoryStream result = new MemoryStream();

    if (collection?.Any() != true)
    {
        await "[]".WriteToStreamAsync(result);//extension from H.Necessaire
        result.Position = 0;
        return result;
    }

    await "[".WriteToStreamAsync(result);//extension from H.Necessaire

    foreach (T entry in collection)
    {
        await entry.ToJsonObject().WriteToStreamAsync(result);//extension from H.Necessaire and H.Necessaire.Serialization
        await ",".WriteToStreamAsync(result);//extension from H.Necessaire
    }

    result.Position -= 1;

    await "]".WriteToStreamAsync(result);//extension from H.Necessaire

    result.Position = 0;

    return result;
}

H.Necessaire NuGets:

Core: https://www.nuget.org/packages/H.Necessaire

Serialization: https://www.nuget.org/packages/H.Necessaire.Serialization


The code above will stream the response (aka send data in chunks) Β to the client instead of doing a full-load/full-dump, thus saving server-side memory and allowing the client to react while the response is downloading. Similar to streaming a video on YouTube.

Needless to say this technique is to be used when the returned payload is huge, because the partial response is obviously not a valid JSON until it's fully loaded!

Which means that the consuming client needs to be aware of this and implement specific techniques to parse the response as it loads. Extra effort!

I'll post a .NET consuming client sample at some point.