//Karthik Srinivasan

Product Engineer, CTO & a Beer Enthusiast
Experiments, thoughts and scripts documented for posterity.

Quirky Personal Projects

LinkedIn

Email me

SignalR - Web Sockets Intro

Jun, 2012

SignalR is a cool asynchronous signaling library for ASP.NET to build real-time applications or for any push based notifications. SignalR is similar to Socket.IO or NowJS. Before the workd of web-sockets, there was Comet which was basically a long-held HTTP requests.

SignalR can be downloaded from NuGet [http://www.nuget.org] and downloading the files manually from Git [https://github.com/SignalR/SignalR]

More descriptive information on SignalR can be found at Scott Hanselman's site [http://www.hanselman.com/blog/AsynchronousScalableWebApplicationsWithRealtimePersistentLongrunningConnectionsWithSignalR.aspx]

To get SignalR up and running following are few todo's on server side:

Step 1 is to create a PersistentConnection class like follows


using SignalR;
using System.Threading.Tasks;

namespace Services
{
public class MyConnection : PersistentConnection
{
protected override Task OnReceivedAsync(string clientId, string data)
{
// Broadcast data to all clients
return Connection.Broadcast(data);
}
}
}

Note that Connection.Broadcast would send the data to all connected clients. If you need to sent to a particular client you can use the Send method.

Send(string clientId, object value);

Note Send requires the intended clientId. If you were to be building a chat client or a custom push service, you probably would be storing clientId's somewhere in a local object or a central repo.

Other useful functions that PersistantConnection class provides that can be overridden:


public void AddToGroup(string clientId, string groupName);
protected virtual void OnConnected(HttpContextBase context, string clientId);
protected virtual Task OnConnectedAsync(HttpContextBase context, string clientId);
protected virtual void OnDisconnect(string clientId);
protected virtual Task OnDisconnectAsync(string clientId);
protected virtual void OnError(Exception e);
protected virtual Task OnErrorAsync(Exception e);
protected virtual void OnReceived(string clientId, string data);
protected virtual Task OnReceivedAsync(string clientId, string data);
public void RemoveFromGroup(string clientId, string groupName);
public void Send(object value);
public void Send(string clientId, object value);
public void SendToGroup(string groupName, object value);



Step 2 is to add the routes if you are using MVC. This route needs to be registered in Global.asax

protected void Application_Start()
{
Bootstrapper.Run();
RouteTable.Routes.MapConnection("Notification", "Notification/{*operation}");
RegisterRoutes(RouteTable.Routes);
AreaRegistration.RegisterAllAreas();
}


That's pretty much it on the server side

Step 3, if the intended client is a web browser it's as easy as follows:

$(function () {
 var connection = $.connection('notification');
<br />

 connection.received(function (data) {
  $('#messages').append('
<li>' + data + '</li>');
 });
<br />

 connection.start(); //start the connection
<br />

 $("#broadcast").click(function () {
  connection.send($('#msg').val());
 });
});
<br />



That's all is to SignalR setup. A chat type client would require some sort of client association on the server side to keep communication private.

But what about non-browser based apps, like a console app or a windows service. SignalR has libraries for those too, can be downloaded from NuGet.

In real world applications, no project ends up with a single instance, single class project. In real world apps, there are many class's and class's are initialized and disposed all the time. In this scenario opening and closing a SignalR connection or instializing a new SignalR object is a wrong approach since you want be connected to the server all time.

One way to keep the connection persistant is to create a static signalR object, in following case it's a singleton class

using SignalR.Client;

public sealed class PushClass
{
private static volatile PushClass instance;
private static object syncRoot = new Object();
private Connection broadcastConnection;

private PushClass()
{
broadcastConnection = new Connection("http://localhost/Notification");
broadcastConnection.Start().Wait();
}

public static PushClass Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new PushClass();
}
}

return instance;
}
}

public void Broadcast(string msg)
{
broadcastConnection.Send(msg);
}
}

A calling class can get an the instance of the above PushClass

var pushInstance= PushClass.Instance;
pushInstance.Broadcast('blah');

Another way but fancier way to achieve the same persistant effect could be like follows:

public class PushClass
{
public static void Broadcast(string data)
{
try
{
var client = new SignalR.Client.Connection("http://localhost/Notification");
var tx = client.Start().ContinueWith(t =>
{
if(t.IsFaulted) Console.WriteLine(t.Exception.GetBaseException()); client.Send(data).ContinueWith(t2 =>{ if(t2.IsFaulted) Console.WriteLine(t2.Exception.GetBaseException());
});
});
tx.ContinueWith(y =>{
if (y.IsFaulted || y.Exception != null)
Console.WriteLine(y.Exception.Message);
});
tx.Wait();
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
The calling class can do the following:

Task asyncSignalr = Task.Factory.StartNew(() => PushClass.Broadcast("blah");

asyncSignalr.ContinueWith(t =>
{
if (t.IsFaulted)
Console.WriteLine(t.Exception.Flatten().ToString());
});