Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
Markdown Monster - The Markdown Editor for Windows

A first look at SignalR


:P
On this page:

SignalR is the latest in a long string of new technologies pouring out from the ASP.NET team recently, when Microsoft rolled out version 1.0 of SignalR when Visual Studio Update 2 was announced.  In a nutshell, SignalR is technology for .NET that allows you to build real time, connected Web applications. Connected in the sense that you can build Web applications that can send and receive and broadcast data in real time. The canonical example of a 'connected' application is a chat application where a client can broadcast messages to all other connected clients. While that's pretty cool in and of itself, that only begins to scratch the surface of what's possible with SignalR as you can communicate in a wide variety of ways between client and server and between all clients to push data around.

Go ahead - Push Me Around!

The idea behind SignalR and other tools like it (like the socket.io or now.js JavaScript libraries) is that you can push data from client to server, from server to client and even from client to client, all in real time without having to poll or check for new data at specified intervals. Callback driven interfaces on both client and server receive pushed messages immediately. The key word here is push - servers and clients can push data at any time and the other end of the connection sees the updated data immediately. It's pretty cool to watch an application, where one browser client updates a value in a text field and all other instances that are connected see that same change at the same time. Or having a server push a notification message down, and having all browsers immediately update to see the new data.

This sort of thing used to be the domain of connected TCP/IP services and peer to peer servers, but SignalR makes all of this available using standard Web protocols, using the HTTP protocol and port 80 or any other HTTP port and with .NET services on the server side. Behind the scenes SignalR combines the use of various connection protocols from WebSockets, to Long Polling to plain AJAX callbacks when all else fails, to bridge the compatibility gap between what modern browsers support and what you can do with legacy browsers. If you want to see all of these techniques highlighted along with a older preview of SignalR, there's a great conference session by Steve Sanderson on Channel 9 that discusses the various Async messaging approaches.

The key feature here is that SignalR's server maintains a persistent connection - abstracted over WebSockets/LongPolling/Ajax depending on what's available on the browser - to the client. So while with AJAX we could always push data to the server, but the server could never push data to the client, with SignalR you can push data both from client to server and from server to client. In order to broadcast messages from one client to all other clients you can callback to the server which can then broadcast a message to all or selected connected clients.

SignalR Server and Client Components

SignalR abstracts these various protocols and allows a seamless experience regardless of what the client supports. Additionally SignalR provides a very easy to use .NET server side framework for creating the backend services that either push data directly or broadcast data in bulk to many clients. SignalR includes the concept of Hubs which use simple methods  in a .NET class as endpoints, as well as a lower level Connection interface that allows for streaming and low level access for the data that is both sent and received. SignalR then also provides rich client libraries for JavaScript, full .NET, Win8, Silverlight and a host of other clients to easily connect to either Hubs or Connections on the server, using an easy to use dynamic mapping model that is very flexible and easy to use. It's surprisingly easy to create SignalR services and consume them, both in Web and non-Web applications.

One of the cool things about SignalR is that you can also easily self host a SignalR server. A typical SignalR server application hosts in ASP.NET and is totally transparent and easy to run as part of the ASP.NET stack. However, you can also host SignalR in a self-hosted application, using an OWIN server host that can bootstrap SignalR and make it available in Console applications, Services or even full blown desktop applications. I recently built a monitoring service application that is running as a Windows Service and was able to use SignalR to efficiently push notification messages to a Web Browser based front end interface, pushing over 50 messages a second to several connected clients in real time. The possibilities this opens up really can't be overstated.

Signal What? A small real World Use Case

When I first heard about SignalR about a year and a half ago, the first thing that came to my mind was: "Yeah that's nice, but it's not a common scenario to have truly connected Web applications." The first thing that springs to mind are chat applications, messaging popups or continuous tickers of updating data pushed down to clients. That demo's nicely and is impressive to see, but it's not exactly a very common use case.

However, recently I had a chance to put SignalR to use in a real application with a scenario that's a little bit different. Specifically we needed a way to connect a standalone Windows Service application  to a Web browser clients to provide real time updates. This project involved a queue service application running as a Windows Service with a Web front end that can monitor and manipulate the queue's operation using any browser.

The specific UI use case was to replace an old and ugly Windows Forms user interface that had to run on the physical server to monitor the real time queue activity and manipulate the queue application settings. With SignalR we were able to move this app to a real time, Web browser based interface.

There are a several important pieces that SignalR provided and made possible for this project:

  • The ability to have a Windows Service push real time messages to a Web browser
  • The ability for many Web browser clients to be connected
  • The ability for many users to modify settings on the Web browser user interface and
    reflect those changes immediately for other browser users

While the application created for this is not very complex it did highlight these various different scenarios of sending messages that you can use with SignalR:

  • Sending messages from the server to all clients (message list display)
  • Sending two-way messages from one client to the server (updates - like AJAX calls but using SignalR)
  • Sending messages from the server a specific caller (individual status updates)
  • Sending messages from a single browser instance to all browsers (Updating the global queue settings or stopping the service)

The interface for this application is basically a list type view of real-time active queue requests as they occur, some status information of the pending items in the queue and the current connection status to the server, as well as a small set of input controls that manage the queue operational status - the number of threads running the wait time and the ability to start and stop the queue.

Here's what the UI for this interface looks like:

QueueViewer

As requests hit the queue they show up in this monitor and the main form's list. The queue service calls SignalR when it starts processing a queue request and again when a queue request either completes successfully or fails. The list status bar then displays the number of pending messages that are  waiting in the queue. The textboxes above let the administrators of this application who have access to the the service manage the queue by tweaking a few settings or by stopping the service altogether. When the update or start/stop button is clicked, a SignalR request is fired to save and or change the service status and then fire a notification to all clients to update their status.

The web site client uses knockout.js for databinding a couple of fairly simple models - the list of visible list items and the queue's status - which are updated by the SignalR callback methods that receive message data from the server. When the model data is updated knockout bindings kick in and refresh the UI immediately resulting in a mostly codeless update process. The only explicit code to display server content are the status messages which are not bound but explicitly called via a showStatus message.

For what it does there's a surprisingly little amount of code involved and the logic involved to make this work is pretty simple.

Granted this isn't a very complex UI, but still it was pretty amazing for me to see hundreds of requests rolling through in a few seconds and updating 10 browser windows simultaneously - until you see this happen with your own application it's hard to appreciate how much satisfaction you get from that very concept working so efficiently! It brings me back to the very early days of the Web when it was exciting to see any dynamic content on a live Web page :-)

I can think of a bunch of use cases where this technology makes a lot of sense:

  • Any sort of two-way messaging applications (chat, messaging)
  • Real time data feeds or ticker displays
  • Real time data monitors for logs, lists, users etc. (Admin interfaces)
  • Long running async requests with real-time status updates
  • A replacement for some Queue type operations with direct real-time connections
  • Screen sharing applications with shared editing data by multiple users
  • Interactive multi-player games with real time screen updates
  • and, and, and…

If you want more technical details of this scenario I have a follow up post that describes the technical implementation in much more detail at:

Ease of Use

Another thing that impressed me about SignalR when I started working with it is that this has to be some of the easiest to use Microsoft technology to come along in a long time, while providing some really powerful features. SignalR is based on dynamic language features which do away with a lot of ceremony in defining of interfaces and mapping client to server. In many cases it's as easy as creating a class on the server and having the client reference the server side hub and method and just call it. End of story. The same is true for broadcasting of messages from the server to the client - there's no contract, no special interface, all you do is call a method that may or may not exist on the client - if you implement it on the client it will get called. End of story - again.

What was really surprising about this project was that going from zero knowledge of SignalR to a fully functional, initial implementation that hit all the initial usage points I mentioned above, took all of 2 work days to accomplish. This included learning about SignalR and experimentation with a few different approaches, dealing with knockout.js, plus building robust connection management code that can deal with disconnects and reconnects (which truthfully was the most complex and time-consuming piece and the only part that required a bit of research and some help on the SignalR Jabbr channel).

This solution uses a Windows Service Project on the server using SignalR's OWIN hosting, which trivial to set up. In fact it takes all of 10 lines of code to hoist up the server.

Low Ceremony

It's extremely easy and low ceremony to broadcast a SignalR message even in a self hosted environment. The following C# server side code calls a JavaScript callback on all clients that are listening  (this method displays a queue list item):

// Write out message to SignalR clients  
HubContext.Clients.All.writeMessage(id,
    "Info",
    DateTime.Now.ToString("HH:mm:ss"),
    message,  
string.Empty);

where the writeMessage method call is translated to the client side JavaScript handler. On the client there's a callback handler registered on a writeMessage operation which is then fired on the client. The script code then proceeds to bind the values to a view model item using knockout.js and updates the display dynamically.

On the client I can simply register a method that handles a callback which effectively 'publishes' that method on the client:

hub.client.writeMessage = self.writeMessage;

And I can then implement the writeMessage callback method that handles this logic (or use an anonymous method):

writeMessage: function (message, status, time, id, elapsed, waiting) { 
… update collection item viewModel and let knockout.js bind }

The server can now call the writeMessage function on the client using the C# code shown above. It's all dynamic.

Calls in the other direction - from client to server are equally simple. The client calls a server method like this (where self is my top level object container and hub is an instance of the SignalR hub stored on it):

self.hub.server.getServiceStatus()
               .fail(page.statusMessage);

This calls a GetServiceStatus() method on the server's hub.

Once a hub has been created and stored you can simply call the server object which maps any methods you call straight to the .NET server methods implemented on the hub. Here's the server code:

public void GetServiceStatus()
{
    var instance = Globals.Controller;
    if (instance == null)
       Clients.Caller.getServiceStatusCallback(null);
    else
       Clients.Caller.getServiceStatusCallback(
         new QueueControllerStatus()
         {
            queueName = instance.QueueName,
            waitInterval = instance.WaitInterval,
            threadCount = instance.ThreadCount,   
            paused = instance.Paused
         });
}

This server code receives the JavaScript client's request and then broadcasts a message back to all connected clients. Effectively this code has a single JavaScript client requesting that the server should broadcast a message to all clients. Here the code basically pushes down status information which is then picked up on the client and bound via knockout to the textboxes and the start/stop button.

The server code can use the Client.All, Clients.Caller, Clients.AllExcept collections to reference common groups or you can add users to specific Groups that you can then broadcast to. Lots of flexibility again in a really easy to use model.

Performance and Resources

Since this was my first time using SignalR I had no idea what to expect in regards to performance with using SignalR's messaging. I was actually surprised that I couldn't overload the UI operation by stuffing even 5000 messages into the queue. SignalR happily and rapidly kept up with the service in sending out messages and updating the list UI faster than you could even begin to keep reading it. 1000 queue requests (x2 for begin/end message) went through in less than 4 seconds! Also tried this with 10 clients connected simultaneously and performance didn't change noticably with the increased number of connected clients.

It's important to understand that this application will be used by a small number of administrative users, so it's not going to be used by thousands of users simultaneously. At most we figure there may be 10 people connected at a time. However, connections are something to consider with SignalR. As cool as this technology is, it's connected technology meaning that each client connected through SignalR is using a persistent and dedicated connection on the Web Server. 10 users or 100 are probably not much of a problem, but thousands of users may bump up against the Web server connection and Windows thread and resource limits eventually. SignalR also includes some scalability features, but these get very complex quickly and if this becomes an issue I personally think that one should reconsider whether SignalR or a real-time connection based interface is the right choice…

While the SignalR's docs claim that it's capable of thousands of simultaneously connected clients (given the connection pool is high enough), there is a finite limit to the amount of connections you can simultaneously run with IIS or self-hosting along with the CPU and memory overhead associated with each connection.

Caveat emptor - make sure you understand the implications of using SignalR in terms of connection, memory, cpu and bandwidth usage.

Documentation and Support

As I mentioned the basics and overall behavior of SignalR are pretty easy to grasp and put into practice and the online documentation does a pretty good job of getting you started and explain the general model of how the messaging flow and program implementation code works. There are nice and simple examples and it works great.

However, some of the more specific documentation is a bit sketchy and often limited or missing altogether. The hardest part of this small component we built was dealing with the connection and disconnection notifications required to determine whether the Windows Service is online and the SignalR server running and how to deal with scenarios where connections are dropped and then reconnecting as necessary. SignalR actually includes some very sophisticated logic to notify you of connect and disconnect events on the client, but there are quite a few overlapping different events that fire on the client and I for one got lost in which one actually needed to be handled to reliably re-connect. There were a handful of other issues at this same lower level that were difficult to resolve through the documentation or even searching.

I also found searching on SignalR content a bit frustrating because a lot of the hits I'd get for topics in blog posts or StackOverflow answers ended up being from preview versions with information that was no longer valid. Hopefully this stuff will work itself out in time.

In the meantime however, I hopped over to the SignalR Jabbr Channel and posted a few of my conundrums over there. There's lots of help offered on this channel from peers and from the authors of SignalR (or David Fowler mostly) frequently jumping in and answering questions. David helped me with two sticky issues and in a few minutes pointed me in the right direction. This type of interactive support is just awesome and it also shows the enthusiasm by some of the people involved with SignalR. I do wonder though how well this type of support will scale in the future. We'll see - in the meantime it's great to see this kind of direct interaction which hopefully helps the SignalR guys iron out some rough spots that come up more frequently.

SignalR - Hell Yeah!

As you can probably tell I'm pretty jazzed about what SignalR offers to .NET developers. Web based real-time communication technology like SignalR offers many opportunities to rethink of what we can actually build with Web applications today, offering many more opportunities to build interactive and collaborative applications. It provides a different way to access information in Web applications in a more direct, real time manner and it does this in a way that is relatively simple to accomplish. SignalR is amongst the cleanest and easiest to implement solutions I've seen coming from Microsoft in a very long time.

I'm especially excited about the ability to interface SignalR's server side code with self-hosted applications that gives us the ability to more easily connect back end services to browser front ends. For administrative applications or dashboards this is incredibly powerful stuff and it's easy to integrate into existing applications. I'll post more on this topic in the future.

But even in plain old Web applications the opportunities to provide real time data or to have users share information across multiple live browser instances is pretty cool. The abstraction provided by SignalR's client and server make it so easy to take advantage of this functionality in just about any application. There are so many opportunities here - from the obvious real time broadcast services to more subdued server callbacks that can replace traditional AJAX interfaces to providing real time access to changing data in Line of Business or even public facing applications. Then there is the use case for running long running async operations on the server and providing real-time feedback to the client page. And there's the whole opportunity with interactive games or productivity applications where multiple users can interact with the same shared information to provide a live and updating interface. Doing simple interactive games like Battleship etc. become almost trivial with this sort of technology and even more interactive graphics intensive   games become a possibility with this toolset.

Lots of opportunities to dream up, so dream on…

Related Resources

Posted in ASP.NET  JavaScript  SignalR  

The Voices of Reason


 

Philip Andersen
May 22, 2013

# re: A first look at SignalR

We have been using SignalR for about a year (when it was just a side project). One thing I though hate is the issue when running on IIS 7 with Windows 7. It simply kills my IIS (http://stackoverflow.com/questions/9697746/when-compiling-a-project-with-signalr-i-have-to-do-a-iisreset).
Are you using IISExpress for development, or have you found a way around this issue?

Tyrone
May 22, 2013

# re: A first look at SignalR

The consideration about performance is really where the team should provide some guidance. I think it's great that you provided some warning to developers to not just dive head first into this without knowing how this may impact a production application.

Jeff Putz
May 22, 2013

# re: A first look at SignalR

I used SignalR in the last release of POP Forums (http://popforums.codeplex.com/), and my users have been really happy with the real-timeyness (not a word) of stuff just appearing on screen. I can't recall any time that adding a new framework to accomplish something novel was this easy.

I also used it in a "live blog" app to cover a roller coaster opening a few weeks ago, and even with 300+ connections, it never broke a sweat. Definitely one of my favorite tools in the tool box!

Ray
May 23, 2013

# re: A first look at SignalR

I've actually dabbled with SignalR myself and instantly fell in love with it. It's such an easy way to be able to push out global or grouped based messages in your web application in real time. I'm glad to see that it's catching some traction in the developer community.

Brendan
May 23, 2013

# re: A first look at SignalR

Any chance of you sharing the source code of the queue application you built? I'm trying to implement this technology and would love to have a working model to look at. Cheers!!

Rick Strahl
May 23, 2013

# re: A first look at SignalR

@Philip - I haven't run into that problem mainly because I've been using self-hosted servers for my work. The limitation there apparently isn't kicking in. But even on IIS on Windows 7/8 Pro you get 10 connections. That should be enough for most test scenarios?

@Brendan - unfortunately I can't with this particular project because it's a customer specific solution. I'll be posting more stuff in the coming weeks though and actually will condense this remote queue manager down to something that I can post as a semi-generic service.

Greg
May 30, 2013

# re: A first look at SignalR

I'm finding the same thing with examples.. Building a self-hosted (owin) service, I can send messages from the host (aka stock ticker), but am having trouble wiring up calls/data from the client for anything other than "chat". I'd love to see your progress published as a simple yet thorough example including host interaction, connection state etc.

Rick Strahl
June 01, 2013

# re: A first look at SignalR

If the hubs are working to send it should also work to receive - there's nothing special to do other than setting up the receiving hub methods and using the client side hub to call the server like this:

hub.server.MethodOnServer(parm1,parm2)              


If you need a 'return' value the server then needs to send a SignalR message from the server to communicate back:

public void MethodOnServer(string parm1,string parm2)
{
   string result = "boo!";
   Clients.Caller.MethodOnServerCallback(result);
}


On the client you register the callback function (and the name is entirely up to you as long as server and client agree on the name):

hub.client.methodOnServerCallback = self.methodOnServerCallback;


which is then called.

Kim See Jonge
June 03, 2013

# re: A first look at SignalR

Hey! Well witten post!
Dont want to ruin the party, but in my opinion SignalR has a long way to go before being great.
Dont get me wrong, it has great potential and the guys building it are awesome developers....

Right now I find SignalR to be bloated and not at all easy and straightforward to use.

I think people are just jumping the gun without thinking about alternatives. For example both Fleck and SuperWebSocket are nice. Not to mention XSocket.NET that has a much better programming model.
All these frameworks have been around longer than SignalR... Just saying. Also... a big disadvantage with SignalR is that you need 2012 server and .NET 4.5 to get websockets. The other transports is just not good enough.

We try to use the right tool for the job/problem and not always is signalr the answer in our book (but sometimes it is).

The thing I do like about SignalR is the javascript proxy, but that´s about it... Hope to see big improvements on SignalR this year!

To sum up... Dont always take for granted that SignalR is the best solution for the task.

Greg Nash
June 03, 2013

# re: A first look at SignalR

My current problem is getting code inside the hub class to invoke code / pass data outside the hub. Do I have to pass a delegate to the hub?

Rick Strahl
June 04, 2013

# re: A first look at SignalR

@Greg - Use Clients.XXXX.ClientMethod(parameter1,parameter2) to call the client. Register the method on the client like I showed in the post above with the right signature to match the parameters you're passing from server method call and then client method will be invoked with those parameters by the server.

Messaging from the server always involves explicitly pushing messages to the Clients.XXX objects to get data to the client. Whatever you push the clients can register and listen for. What you pass can be anything that can serialize into JSON.

Geoff Hudik
June 08, 2013

# re: A first look at SignalR

I'm curious how you communicated between win svc and web app; when I try it I either run into x-domain issues such as http://stackoverflow.com/questions/9984534/signalr-cross-domain-connections-cors-access-control-allow-origin-issues or I set the server URL in $.connection and it can't see the hub.

Fallon
June 15, 2013

# re: A first look at SignalR

@Kim See Jonge - Most of what you've said is 100% not true!

We're running SignalR on Windows Server 2003 with .Net Framework 4.0 with absolutely no problems!

As a matter of fact, the Katana project also supports Windows Server 2003, which our client simply won't upgrade yet, LOL!

IMO, we will use SignalR on EVERY project except for the really simple ones, it's becoming an essential feature for us!

Alex Jitbit
August 11, 2013

# re: A first look at SignalR

@Kim See Jonge - Nope, it does work fine on older versions of Windows Server. We're using it with our chat application hosted on Server 2008 and IIS7 just fine, and were even using Windows 2003 before that.

Rick Strahl
August 11, 2013

# re: A first look at SignalR

@Alex - I haven't tried it personally, but while I think it works just fine, it doesn't use Web Sockets on non-Windows 8/2012 servers, so you get fallback to long polling. Same is unfortunately true of self-hosting I think.

Tomas Andersson
October 09, 2013

# re: A first look at SignalR

Nice post Rick!

I like SignalR, but I have to give some credit to Kim See Jonge since he/she is right about SignalR. If the server does not have 2012/Win8 & .NET 4.5 you have SSE or longpolling... Unfortunatelly this is also true for the signalR client API.

I have never used xsockets that Kim talks about, but I´ve read the comparison between xsockets and signalr http://xsockets.net/xsockets-vs-signalr

It seems like it is xsockets that has been writing the comparison, but if the facts are right I will give xsockets a try in my next project.

Fallon
October 24, 2013

# re: A first look at SignalR

@Tomas Andersson - Yes XScokets looks very nice. My only problem with them is that they are not open source like SignalR.

Actually I'm shocked that I'm saying somebody else is not open source and Microsoft is :)

However, if you can live with that, XSockets looks really good!

Eric
November 26, 2013

# re: A first look at SignalR

I'm wanting to do exactly (well, close) what you've done, in that I want a Windows Service based, hub server. Two things I'm not clear on:

1) If I want multiple hubs, contained in the same Windows Service, is it simply a matter of creating a new one, derived from Hub? Or is there more to it?

2) How do you receive messages from a client?

Rick Strahl
November 27, 2013

# re: A first look at SignalR

@Eric - You can easily configure multiple hubs in a single server - you just register each hub's configuration consecutively.

I have another post that describes this scenario with all the specific details - this post is a high level overview only. You can find the other post at:

http://weblog.west-wind.com/posts/2013/Sep/04/SelfHosting-SignalR-in-a-Windows-Service

West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2024