AspNetCore.Docs.Samples/fundamentals/streaming/SynchronousWithNewtonsoftJson/Middleware/SongLyricsMiddleware.cs

57 lines
2.0 KiB
C#

namespace SynchronousWithNewtonsoftJson.Middleware;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using SynchronousWithNewtonsoftJson.Model;
public class SongLyricsMiddleware
{
RequestDelegate _next;
ILyricsSource _lyricsSource;
JsonSerializer _serializer;
public SongLyricsMiddleware(RequestDelegate next, ILyricsSource lyricsSource, JsonSerializer serializer)
{
_next = next;
_lyricsSource = lyricsSource;
_serializer = serializer;
}
public Task InvokeAsync(HttpContext context)
{
if (!context.Request.Path.StartsWithSegments(new PathString("/middleware/sing")))
return _next(context);
else
return InvokeAsyncImplementation(context);
}
static readonly byte[] JSONArrayStart = new byte[] { (byte)'[' };
static readonly byte[] JSONArraySeparator = new byte[] { (byte)',' };
public async Task InvokeAsyncImplementation(HttpContext context)
{
await context.Response.Body.WriteAsync(JSONArrayStart, context.RequestAborted);
while (true)
{
foreach (string line in _lyricsSource.GetSongLyrics())
{
// Since we are performing our own writes outside of the JsonTextWriter, we need it to be logically
// set up and torn down for each object we output. Simply calling Flush() might work in practice but
// is assuming internal implementation details.
using (var streamWriter = new StreamWriter(context.Response.Body))
using (var jsonWriter = new JsonTextWriter(streamWriter))
_serializer.Serialize(jsonWriter, line);
await context.Response.Body.WriteAsync(JSONArraySeparator, context.RequestAborted);
await context.Response.Body.FlushAsync(context.RequestAborted);
await Task.Delay(200);
}
}
// No JSONArrayEnd needs to be written, because the above loop will never exit.
}
}