Self Hosted SignalR And MSMQ

Standard

Me and my colleagues at Communited are really impressed by SignalR. SignalR simplifies the development of aync web applications. In short, it exposes server-side methods to the client JavaScript, and client JavaScript methods to the server, in a transparent way. See this blog post by Scott Hanselman for more explanation.

A lot of the examples on internet host a SignalR Hub within the same context as the web-application. For one of our products, we needed a way of notifying users about events that occure in other processes than the web-application.

To accomplish this, we thought it would be an idea to use Microsoft Message Queueing (MSMQ) to broadcast messages by processes, pick up these messages with a windows service, which hosts a SignalR Hub, with which we can notify our users.

I made a little Proof Of Concept, and because there aren’t a lot of examples of self hosted SignalR Hubs online, I thought I post it here. :)

The example consists of 3 little projects:

  1. A simple windows form application. This one does nothing else but putting messages on a private queue.
  2. A console application. I made this instead of a windows-service for simplicity. This application reads the queue, and sends the messages to the clients via SignalR.
  3. A web application, consisting of nothing more than one static html file and some scripts. This html file references the SignalR Hub JavaScripts hosted by the console application, jquery, and the SignalR library. It shows the messages broadcasted by the console application.

Before getting started, make sure MSMQ is installed on your machine. Check here for info.

The windows form application is not much really. It opens the queue to write to (or creates it, if it doesn’t exist), and writes the string the user inputs to this queue.

The console app is where the action is. The SignalR.Hosting.Self package is added to this project. I’ve created the most simple SignalR Hub:

public class SignalRHub : Hub {
}

For this example, I haven’t put any server-side code in the hub, I’ve just used it to call my client-side code from the server.

The main method starts a self hosted server hosting the hub Javascript, opens the queue, and starts waiting for messages to arrive. When a message arrives, I create a new myMsg object, assign a little counter and the string-message to it, and call the client-side addMessage method. That’s it!

        static void Main(string[] args)
        {
            string url = "http://localhost:8081/";
            var server = new Server(url);

            // Map the default hub url (/signalr)
            server.MapHubs();

            // Start the server
            server.Start();
            var context = GlobalHost.ConnectionManager.GetHubContext<SignalRHub>();

            Console.WriteLine("Server running on {0}", url);

            //Open the queue
            MessageQueue channel;
            if (!MessageQueue.Exists(queueName))
            {
                channel = MessageQueue.Create(queueName);
            }
            else
            {
                channel = new MessageQueue(queueName);
            }
            channel.Formatter = new XmlMessageFormatter(new Type[] { typeof(String) });

            int counter = 0;
            while (true)
            {
                //read next message from server
                string newMsg = (string)channel.Receive().Body;
                Console.WriteLine(newMsg);

                //create a message object
                myMsg m = new myMsg() ;
                m.count = ++counter;
                m.msg = newMsg;
                
                //Call the (clientside) javascript function via the hub.
                context.Clients.addMessage(m);
            }

        }

The last part of the solution is the webproject. After referencing the needed scripts, I’ve declared the function addMessage on the hub, which is invoked by the server. This function does nothing more than adding the messages to a list.

<!DOCTYPE html>
<html>
<head>
    <title>SignalR client</title>
    <script type="text/javascript" src="Scripts/jquery-1.6.4.min.js"></script>
    <script type="text/javascript" src="Scripts/jquery.signalR-0.5.1.min.js"></script>
    <script type="text/javascript" src="http://localhost:8081/signalr/hubs"></script>
    <script type="text/javascript">
        $(function () {
            // Proxy created on the fly
            var myHub = $.connection.signalRHub;

            // Declare a function on the hub so the server can invoke it
            myHub.addMessage = function (message) {
                $('#messages').append('<li>received: ' + message.count + ' : ' + message.msg + '</li>');
            };

            // Start the connection
            $.connection.hub.url = 'http://localhost:8081/signalr';
            $.connection.hub.start();
        });
        
    </script>
</head>
<body>
    <ul id="messages">
    </ul>
</body>
</html>

And that’s it! You can download the full project here. Enjoy!

About these ads

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s