First, read up on Comet; a basic way to have real-time notifications sent to a browser (like push notifications). One common Comet technique involves “Long Polling” an http connection. What this means is that we call out to a URL that expects to wait around for a long time before something happens.

The first step for the chat server was to create a new Async Controller (Async what? Check out this great introduction to Async Controllers) to handle our Long Poll requests. Here is the ChatController I created:

You can see that we’ve created our Index action as an Async that calls our to our ChatServer and checks for a message to arrive. By default, I’ve specified a 60 second time limit before returning an empty list of messages, but you could theoretically let this go on for hours waiting for a response. Once a response comes back from the ChatServer, we tell the AsyncManager we are done and return our messages in JSON form.

The ChatServer

I chose to use Observables and the Reactive (Rx) Framework to have a synchronized way of notifying all interested parties when a new message comes in. To do this, I took advantage of the Subject<T> class that wraps a lot of the Observable and Observer implementation details. To handle persisting my chat history, I use a simple Queue to keep the last 100 or so by default. Whenever a new message comes in, I check the history length and pop off anything over the limit, then push in my new messages. Yes, eventually I’d have to figure out a strategy for pushing this back to a database or Redis cache server thingy but this is just a demo, so relax.

On the client side, we need to take advantage of some of jQuery’s helper methods for POSTing to an MVC Action (the Index Action on the Chat Controller in our case). We are going to make a POST call to /Chat that will sit around until a new message arrives, or our 60 second timeout is reached. If a new message comes in, our POST call will return immediately with the new message(s). From there, we just insert them into our current chat history.