Quantcast
Channel: ASP.NET Core
Viewing all articles
Browse latest Browse all 9386

dnx451 + Middleware + Server Send Events

$
0
0

Hello,

im trying to implement simple POC for Server Send Events using middleware in asp.net core... this is what i have so far:

Server:

using System;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Http;

namespace cshdd.Middlewares
{
    public class ServerSendEventsMiddleware
    {
        private readonly RequestDelegate _Next;
        private readonly string _Url;

        public ServerSendEventsMiddleware(RequestDelegate next, string url) {
            _Next = next;
            _Url = url;
        }

        public async Task Invoke(HttpContext httpContext) {
            if (httpContext.Request.Path.Value == _Url) {
                Initialize(httpContext);
//await InitializeAsync(httpContext); return; } await _Next(httpContext); } private void Initialize(HttpContext httpContext) { httpContext.Response.Clear(); httpContext.Response.ContentType = "text/event-stream"; httpContext.Response.Headers.Add("Cache-Control", "no-cache"); httpContext.Response.Headers.Add("Connection", "keep-alive"); httpContext.Response.Headers.Add("Keep-Alive", "timeout=15, max=100"); var stream = httpContext.Response.Body; // block 1 using (var writer = new StreamWriter(stream, Encoding.UTF8, 4096, true)) { writer.Write("data:initialize\n\n"); writer.Flush(); } // block 2 Task.Run(() => { using (var writer = new StreamWriter(stream, Encoding.UTF8, 4096, true)) { for (int i = 0; i < 10; i++) { writer.Write("data:test + " + i + " \n\n"); writer.Flush(); Thread.Sleep(1000); } } }); } private async Task InitializeAsync(HttpContext httpContext) { httpContext.Response.Clear(); httpContext.Response.ContentType = "text/event-stream"; httpContext.Response.Headers.Add("Cache-Control", "no-cache"); httpContext.Response.Headers.Add("Connection", "keep-alive"); httpContext.Response.Headers.Add("Keep-Alive", "timeout=15, max=100"); var writer = new StreamWriter(httpContext.Response.Body, Encoding.UTF8, 4096, true); writer.Write("data:initialize\n\n"); await writer.FlushAsync(); for (int i = 0; i < 10; i++) { writer.Write("data:test + " + i + " \n\n"); writer.FlushAsync(); Thread.Sleep(1000); } } } }

Client: (jQuery is not needed but for simplicity ...)

$(function () {
    var source = new EventSource(url); // url is same value as in ServerSendEventsMiddleware ctor on server
    console.log("init");

    source.addEventListener("message", function (e) {
        console.log("message: " + e.data);
    }, false);

    source.addEventListener("open", function(e) {
        console.log("open");
    }, false);

    source.addEventListener("error", function(e) {
        if (e.target.readyState === EventSource.CLOSED) {
            console.log("error: CLOSED");
        } else if (e.target.readyState === EventSource.CONNECTING) {
            console.log("error: CONNECTING");
        }
    }, false);
});

- block 1 works fine
- block 2 throws null references exception on writer.Flush()  - probably because by that time httpContext.Response.Body is set to null
- async method will return result to client after it is completed and not on first await writer.FlushAsync();

one of recommendations i found on the internet is to set Response.BufferOutput to false but i cannot find any property or method with similar name on httpContext / httpResponse used in asp.net core ...

And my question at last:

How to create open connection with client without closing it? Eg: client send request, server sends back empty response and stores response stream somewhere, then some time later server writes message into stored stream and client react on it.

Cheers.

PS: not sure if this is usefull but my project.json looks like this:

{"userSecretsId": "cshdd-329afda3-c19b-499b-98bb-8ed98fe6fd18","version": "1.0.0-*","compilationOptions": {"emitEntryPoint": true
  },"dependencies": {"AspNet.Hosting.Katana.Extensions": "1.0.0-alpha1","AspNet.Identity3.MongoDB": "2.1.0-*","Microsoft.AspNet.Authentication.Cookies": "1.0.0-rc1-final","Microsoft.AspNet.Authentication.Facebook": "1.0.0-rc1-final","Microsoft.AspNet.Diagnostics.Entity": "7.0.0-rc1-final","Microsoft.AspNet.Identity": "3.0.0-rc1-final","Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final","Microsoft.AspNet.Mvc": "6.0.0-rc1-final","Microsoft.AspNet.Mvc.TagHelpers": "6.0.0-rc1-final","Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final","Microsoft.AspNet.StaticFiles": "1.0.0-rc1-final","Microsoft.AspNet.Tooling.Razor": "1.0.0-rc1-final","Microsoft.Extensions.CodeGenerators.Mvc": "1.0.0-rc1-final","Microsoft.Extensions.Configuration.FileProviderExtensions": "1.0.0-rc1-final","Microsoft.Extensions.Configuration.Json": "1.0.0-rc1-final","Microsoft.Extensions.Configuration.UserSecrets": "1.0.0-rc1-final","Microsoft.Extensions.Logging": "1.0.0-rc1-final","Microsoft.Extensions.Logging.Console": "1.0.0-rc1-final","Microsoft.Extensions.Logging.Debug": "1.0.0-rc1-final","Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0-rc1-final","Facebook": "7.0.10-beta","SharpZipLib": "0.86.0"
  },"commands": {"web": "Microsoft.AspNet.Server.Kestrel"
  },"frameworks": {"dnx451": { }
  },"exclude": ["wwwroot","node_modules"
  ],"publishExclude": ["**.user","**.vspscc"
  ],"scripts": {"prepublish": [ "npm install", "bower install", "gulp clean", "gulp min" ]
  }
}


Viewing all articles
Browse latest Browse all 9386

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>