Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
583 views
in Technique[技术] by (71.8m points)

c# - ASPNET Core Server Sent Events / Response flush

While there is no official documentation, does anyone know how SSE may be implemented using ASP.NET Core?

I suspect one implementation may use custom middleware, but maybe it is possible to do that in controller action?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Client Side - wwwroot/index.html

On page load, create an EventSource for the http://www.somehost.ca/sse url. Then write its events to the console.

<body>
    <script type="text/javascript">

        var source = new EventSource('sse');

        source.onmessage = function (event) {
            console.log('onmessage: ' + event.data);
        };

        source.onopen = function(event) {
            console.log('onopen');
        };

        source.onerror = function(event) {
            console.log('onerror');
        }

    </script>
</body>

Server Side Alternative #1 - Use Middleware

The middleware handles the sse path. It sets the Content-Type header to text/event-stream, which the server socket event requires. It writes to the response stream, without closing the connection. It mimics doing work, by delaying for five seconds between writes.

app.Use(async (context, next) =>
{
    if (context.Request.Path.ToString().Equals("/sse"))
    {
        var response = context.Response;
        response.Headers.Add("Content-Type", "text/event-stream");

        for(var i = 0; true; ++i)
        {
            // WriteAsync requires `using Microsoft.AspNetCore.Http`
            await response
                .WriteAsync($"data: Middleware {i} at {DateTime.Now}

");

            await response.Body.FlushAsync();
            await Task.Delay(5 * 1000);
        }
    }

    await next.Invoke();
});

Server Side Alternative #2 - Use a Controller

The controller does the exact same thing as the middleware does.

[Route("/api/sse")]
public class ServerSentEventController : Controller
{
    [HttpGet]
    public async Task Get()
    {
        var response = Response;
        response.Headers.Add("Content-Type", "text/event-stream");

        for(var i = 0; true; ++i)
        {
            await response
                .WriteAsync($"data: Controller {i} at {DateTime.Now}

");

            response.Body.Flush();
            await Task.Delay(5 * 1000);
        }
    }
}

Client Side Console Output in Firefox

This is the result in the Firefox console window. Every five seconds a new messages arrives.

onopen
onmessage: Message 0 at 4/15/2016 3:39:04 PM
onmessage: Message 1 at 4/15/2016 3:39:09 PM
onmessage: Message 2 at 4/15/2016 3:39:14 PM
onmessage: Message 3 at 4/15/2016 3:39:19 PM
onmessage: Message 4 at 4/15/2016 3:39:24 PM

References:


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...