Home > front end >  ASP.NET Core API Endpoint which delivers a Stream instead of big JSONArray
ASP.NET Core API Endpoint which delivers a Stream instead of big JSONArray

Time:02-11

I have a pretty big list of objects, which needs to be received fast from the client. Currently it takes about 2-4 seconds. I now try to use streams to send chunks (e.g. 100 objects in each) I know that GRPC can use streams but in ASP.NET core, how can I achieve this? The normal ASP.NET has PushStreamContent which is not available in Core. Any solutions out there? I can't really find a proper one online.

So what my Controller currently looks like:

 [HttpGet]
 public async Task<ActionResult<IEnumerable<Price>>> GetPrices()
 {
     return await _context.Prices.ToListAsync();
 }

This list currently contains around 18700 Items but this number will increase by time.

CodePudding user response:

I'm guessing you're using EF Core based on your example.

If you take a look at Efficient Querying - Buffering and streaming, they recommend using AsEnumerable to stream the data instead of ToList, which essentially loads all data into memory before (in your case) returning it to the client. The async version is AsAsyncEnumerable.

So you should be able to simply change your controller action into:

[HttpGet]
public async Task<ActionResult<IEnumerable<Price>>> GetPrices()
{
    return await _context.Prices.AsAsyncEnumerable();
}

Note, that streaming rather than buffering/loading into memory does not mean performance improvements in all cases, but with a large dataset there's a good chance you'll see better performance.

is it a code smell / bad practice to send such big JSON data?

Not necessarily. If you actually need to have the entire dataset client-side, then this is probably the most efficient approach. However, if your dataset is large, you should expect that it takes some time to download. If your download speed is 5 MB/s and your Price data is 10 MB, then you'll never make it faster than 2 seconds without a better connection. Even if you use a stream from your backend.

Another approach (if that fits your needs) is to introduce paging. That way you can retrieve e.g. 50 items at a time instead of everything and then page through it. But whether it makes sense to use paging from your client is up to you.

  • Related