Search code examples
asp.netangularjsgoogle-chromeeventsserver-side

'Server side events' send with the ASP Web Api do not arrive?


I created a test source which should send a message to the client every x time. This is the ApiController:

public class TestSourceController : ApiController
{
    private static readonly ConcurrentQueue<StreamWriter> ConnectedClients = new ConcurrentQueue<StreamWriter>();

    [AllowAnonymous]
    [Route("api/sources/test")]
    public HttpResponseMessage Get()
    {
        var response = Request.CreateResponse();
        response.Content = new PushStreamContent((Action<Stream, HttpContent, TransportContext>) OnStreamAvailable,
            "text/event-stream");
        return response;
    }

    private static void OnStreamAvailable(Stream stream, HttpContent headers, TransportContext context)
    {
        var clientStream = new StreamWriter(stream);
        ConnectedClients.Enqueue(clientStream);
    }

    private static void DoThings()
    {
        const string outboundMessage = "Test";

        foreach (var clientStream in ConnectedClients)
        {
            clientStream.WriteLine("data:" + JsonConvert.SerializeObject(outboundMessage));
            clientStream.Flush();
        }
    }
}

The clientStream.Flush(); is called like expected and without exceptions.

I handle it in AngularJS like this:

    $scope.handleServerCallback = function (data) {
        console.log(data);

        $scope.$apply(function() {
            $scope.serverData = data;
        });
    };


    $scope.listen = function () {
        $scope.eventSource = new window.EventSource("http://localhost:18270/api/sources/test");
        $scope.eventSource.onmessage = $scope.handleServerCallback;
        $scope.eventSource.onopen = function() { console.log("Opened source"); };
        $scope.eventSource.onerror = function (e) { console.error(e); };
    };

    $scope.listen();

My guess is it's a problem with the server since I can see the "EventStream" from the test call is empty in the chrome debugger.

Does anyone know how to make sure the messages arrive at the client?


Solution

  • The solution was quite easy, according to the spec every line has to end with "\n" and the very last line with "\n\n".

    So:

    clientStream.WriteLine("data:" + JsonConvert.SerializeObject(outboundMessage) + "\n\n");
    

    Solves it.