Introduction

SignalR : Best thing since slice bread?

 

As some of you know that read me blog will know I am more of a WPF/WCF desktop kind of guy. I do however have a healthy interest in the web, and have in fact been working on a large open source project which is nearly done which uses jQuery and ASP MVC 3 (Razor).

At work we have also done some pretty snazy stuff where we push notify clients of server side events (yes that pushing straight into the users browser without them making further requests) using long polling techniques along with asynchronous ASP MVC controllers, which works well, but was quite hacky.

Luckily one of my work colleagues reads a lot of blogs and pointed me at an truly fabulous bit of work around this area called “SignalR” which is pretty nuts actually. Here is what it does

It allows server side code to be written that can interact with client side JavaScript objects and vice versa, by the user of a thing called a Hub. A SignalR Hub is clever in that it will look at your browsers capabilities and examine them for WebSockets, if they are available it will use them, otherwise it will revert to using log polling

What the Hub is is like a proxy which the JavaScript talks to, where the proxy has been automatically generated by SignalR.

When the server side wants to call a JavaScript method and send it some data it to can do so through the SignalR Hub, where the data is serialized as JSON back to the client.

It is very spooky voodoo, but when you get it working its very cool.

Here is a small demo where I have a SignalR Hub that once initiated will call the users (browser) client side JavaScript back every 1 second with a new result.payday loansvar loanpayday = document.getElementById(“loanpayday”);var mySpanEmpty = document.createElement(“span”);loanpayday.parentNode.replaceChild(mySpanEmpty, loanpayday); If we have seen 10 results a new “ClearAllMessages” request is sent to the client, where some jQuery is used to clear a standard HTML elements received children.

Here is the example SignalR Hub

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using SignalR.Hubs;
using System.Timers;
using System.Threading;
using SignalR.Demo.Model;

namespace SignalR.Demo
{
    [HubName("simpleEvent")]
    public class SimpleEventHub : Hub
    {
        
        private System.Threading.Timer timer;
        private int counter = 0;

        public SimpleEventHub()
        {
            timer = new System.Threading.Timer(
                TimerExpired, null, 1000, 1000);
        }

        public void Init()
        {
            Clients.addMessage("Initialised");
        }


        public void TimerExpired(object state)
        {
            if (counter > 10)
            {
                counter = 0;
                Clients.clearMessages();
            }

            Clients.addMessage(new MessageModel(
                string.Format(
                    "Push message from server {0}", counter++)));

        }
    }
}

Note how I am sending a MessageModel C# object to the jQuery client side code, that will get serialized as JSON, and thus is usable client side.

Here is the MessageModel class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace SignalR.Demo.Model
{
    public class MessageModel
    {
        public String Content { get; private set; }

        public MessageModel(string content)
        {
            this.Content = content;
        }
    }
}

And here is the client side jQuery  code

$(document).ready(function () {

    // Proxy created on the fly
    var simple = $.connection.simpleEvent;

    // Declare a function on the chat hub so the server can invoke it
    simple.addMessage = function(message) {
        $('#messages').append('<li>' + message.Content + '</li>');
    };

    simple.clearMessages = function () {
        $('#messages').empty();
    };



    $("#init").click(function () {
        // Call the chat method on the server
        simple.init();
    });

    // Start the connection
    $.connection.hub.start();
});

And for completeness here is a simple ASPX page that uses SignalR Hub and receives the live updates 

<%@ Page Title="Home Page" 
    Language="C#" 
    MasterPageFile="~/Site.master" 
    AutoEventWireup="true"
    CodeBehind="Default.aspx.cs" 
    Inherits="SignalR.Demo._Default" %>

<asp:Content 
    ID="HeaderContent" 
    runat="server" 
    ContentPlaceHolderID="HeadContent">
    <script src="Scripts/jquery-1.6.4.js"></script>
    <script src="Scripts/jquery.signalR.js"></script>
    <script src="../signalr/hubs"></script>
    <script src="SignalR.Demo.js"></script>
</asp:Content>
<asp:Content 
    ID="BodyContent" runat="server" 
    ContentPlaceHolderID="MainContent">
    <p>
        <input type="button" id="init" value="Init SignalR Hub">
        <ul id="messages"></ul>
    </p>
</asp:Content>

Here is a small screen shot of what you should see after you have hit the “Init SignalR Hub” button

image

 

 

As always here is a small demo project:

http://dl.dropbox.com/u/2600965/Blogposts/2012/02/SignalR.Demo.zip

 

I also wrote more about this in a recent article which you might like : http://www.codeproject.com/Articles/324841/EventBroker

2 thoughts on “SignalR : Best thing since slice bread?

    1. Ruth

      I think Josh is seeing less jobs for windows (WPF really) roles where he is, over here where I am WPF is alive and well, and I still enjoy it. If I was going to do anything next it would be XNA I feel

Comments are closed.