Building a little chat for EPiServer using SignalR

Recently I saw a forum thread over at EpiServer world that asked for chat functionality and since I had previously toyed around with the basic idea I decided to write a quick POC. Like Fredrik says it can be implemented using SignalR. SignalR is in their own words an “async signaling library for .NET to help build real-time, multi-user interactive web applications”. So let’s take a look at what’s needed to implement a very basic chat using the Alloy Tech template package. (And yes, a chat examples is to SignalR what a shopping cart is to a DDD sample but bare with me).

Installing SignalR

SignalR is only available for .Net 4 so first step is to change the target framework to .Net 4. We also need to update various config settings for EPi to work which is easily done through nuget package manager console Install-Package EPiServerCMS6ToNetFour. After that is done the installation of SignalR is as simple as Install-Package Signalr

We also need to add a few javascript references

<script type="text/javascript" src="<%=ResolveUrl("~/Scripts/jquery-1.6.4.min.js")%>"></script>
<script type="text/javascript" src="<%=ResolveUrl("~/Scripts/jquery.signalR.min.js")%>"></script>
<script type="text/javascript" src="/signalr/hubs"></script>

The last one referencing “/signalr/hubs” perhaps looks a bit weird. You can just consider it magic bootstrapping needed to make hubs in SignalR work.

Backend

We will be communicating through a Hub. Creating a hub is a simple process.

public class Chat : Hub
{
    public void SendMessage(string message)
    {
        Clients.addMessage(message);
    }
}

Everything declared as a public method on our Hub will be callable from javascript side (shown in a second). When inheriting from hub you get access to, amongst other things, all clients connected to the hub. To call a method on these clients you simply specify the method name in the client side javascript.

Frontend

This side of the fence simply consist of a text box (#message), a button (#send) and a ul list (#messages). When you click the button it calls the hub method with the text entered in the text box which in turns calls a method on the clients that adds a li element to the ul with the actual message sent.

$(function () {
    var chat = $.connection.chat;

    $.connection.hub.start(function () {});

    $("#send").click(function () {
        chat.sendMessage($("#message").val());
    });

    chat.addMessage = function (message) {
        $("#messages").append("<li>" + message + "</li>");
    };
});

This pretty color coded picture shows how these parts tie together.

EPiChievements

The chat is basically a very simplistic approach and there is obviously much, much more that can be done with SignalR. For instance, how do we communicate with the clients of a hub outside of the hub? Let’s imagine that we’re building an edit mode achievement system (called EPiChievement) and when a user unlocks one we want to notify the users surfing the site (no, I’m not recommending using this on a real site). In an initializable module we attach ourselves to the PagePublished event.

void PublishedPage(object sender, PageEventArgs e)
{
    var connectionManager = AspNetHost.DependencyResolver.Resolve<IConnectionManager>();
    dynamic clients = connectionManager.GetClients<Chat>();
    clients.addMessage(string.Format("{0} was saved by {1}", e.Page.PageName, e.Page.ChangedBy));
}

Then it’s simply asking the dependency resolver for a connection manager which in turn can give us all the clients of our chat hub. We can then call addMessage precisely as we did before.