Servicestack server sent events

2019-05-29 19:28发布

问题:

I just started messing with my own implementation of ServiceStack server events.

After reading the wiki section and reading the code of the chat application, I started creating my own new mvc4 project and installing all the ServiceStack libraries via nuGet.

After configuring and creating the AppHost, I created a new "helloworld" service and started the site, just to make sure it worked (it worked indeed).

Now the main issues. Based on the existing example code (the chat application), I created the new HTML page and the service which calls ServerEvents.NotifyChannel and then I started the new site.

When calling the service via ajax (post) the debugger hits the break point, but the client events aren't fired when the service returns. Even more, it seems that the notify is sort of "cached/delayed" and when calling the service the second time, the client receives the data from the first call.

Should I use servicestack.razor views? Should I create another MVC application and again, build everything from scratch to test it?

editing this post to add code (as pointed out): https://github.com/xspadax/SS_SSE_Test

回答1:

This issue is due to Flush() not working properly in ASP.NET MVC projects which seems to automatically buffer when compression is enabled, it can be disabled for dynamic pages with:

<system.webServer>
  <urlCompression doStaticCompression="true" doDynamicCompression="false" />
</system.webServer>

Incidentally not even the explicit API for Buffering output seems to have any effect when compression is enabled:

Response.BufferOutput = false;

Normal ASP.NET projects that don't use ASP.NET MVC like ServiceStack + Razor doesn't have this issue.

Alternative code-only solution

New API's were added in v4.0.32+ that's now available on MyGet to provide more custom hooks into ServiceStack's Server Events Feature, OnInit can be used to modify the HTTP Headers of the Server Events Stream, whilst the OnPublish() callback is fired after every message is published:

Plugins.Add(new ServerEventsFeature { 
    /*
    OnInit = req => { //fired when sending headers in server event stream
        var res = (HttpResponseBase)req.Response.OriginalResponse; //Get MVC Response
        res.BufferOutput = false; // Should make Flush() work, but doesn't
    },
    */
    OnPublish = (res, msg) => { //fired after ever message is published
        res.Write("\n\n\n\n\n\n\n\n\n\n");
        res.Flush();    
    }
});

The solution above involves writing a number of trailing \n lines to force a flush in MVC. It's a valid alternative solution as trailing new lines are ignored in Server Sent Events.