ASP.NET SignalR: Old-fashioned Polling, Just Done Better

A website often needs to update a page as the underlying data changes. You can, of course, just poll the server every few seconds on the browser via JavaScript, but to receive live updates from a site it is better to push data to the browser, using server-based SignalR. This uses web sockets to do this rather than browser-based polling where web sockets are supported on the browser. Dino explains how.

Since the early days of Ajax, web developers struggled to make their pages capable of receiving and showing real-time updates. It’s really a nice experience for users when they open a given page, read the content, and then receive updates to the content when and if changes occur and are detected. The difficulty of having live web pages is all here, in the combined effect of the two expressions “changes occur” and “are detected”.

The content that web pages display comes from the output of some backend layer. Live content is therefore the result of some server-side processing that happens asynchronously with the rendering and display of the page. A common example is a page that presents results of some live event, whether football games, tennis tournaments, hashtag battle, but also a page that starts a long-running task and reports about its progress.

By the very nature of web pages and web sites, it is not an easy task to receive live updates in the browser. While not impossible at all-and hundreds of web sites out there can witness it-live web pages require an ad hoc design and the use of special frameworks. At its core, a live page needs a mechanism to call back the server environment to know about changes and a mechanism to refresh the current content. Combined together, Ajax (via jQuery and Web Services) and the dynamic document object model (DOM) that browsers implement can definitely solve the problem. But this is just one solution and not necessarily the most effective. This solution is based on polling and, while effective, may involve an excessive use of resources and generate too much web traffic.

In this article, I’ll start from here and then discuss the structure of live web pages and rework the classic solution to use ASP.NET SignalR.

The Classic Pattern: Poll-and-Refresh

Since the advent of the dynamic DOM in the late 1990s, it has no longer been a problem to modify the entire body of a displayed web page, though it was still tricky to bring live and real-time data down to the page, until this problem was solved with XML Web services first and JSON endpoints next combined with an easy-to-use JavaScript library like jQuery. The final issue was then: how to force the browser to get new data when new data was available?

For the architecture of web solutions it was not easy to take the step of having the server push back data to the client. Most solutions were implemented with a plain JavaScript timer that called a query function at every interval.

As in the example, you can use one of the numerous methods of the jQuery library to connect to a URL, grab a chunk of HTML and have the library to attach it right in the body of the specified HTML element-for example a DIV element. The first parameter of the browser’s setTimeout method takes the JavaScript function to call repeatedly; the second parameter indicates the length of the interval in milliseconds. As a result, as of the previous example, the content of the liveDataContainer HTML element is updated every twenty seconds with whatever HTML is returned by the specified URL.

In ASP.NET MVC, you can easily create such a HTML endpoint using a partial view. Here’s an example:

The project is assumed to have a _live.cshtml file defined to render a chunk of HTML-not a full page-merging a predefined template with live data passed through the view model data container.

Inspired by one of the very first Ajax patterns, this approach works beautifully and there are no reasons to believe that, functionally speaking, it will be less effective than this in the near future. It should also be noticed that this approach doesn’t even require deep knowledge of JSON, JavaScript frameworks or the intricacies of client-side programming. In a way, this approach is just a more modern and smoother version of the classic refresh meta tag.

Placed in the head section of the page, the refresh meta tag instructs the browser to fully refresh the page every specified number of seconds. The JavaScript approach is smoother as it only refreshes the specified segment of the DOM.

JSON-based Poll-and-Refresh

The previous approach makes the page a lot more responsive and pleasant to work with but still keep a bunch of pressure on the server side. This point has been debated quite a bit lately. What’s the tradeoff of having work done on the client and/or the server? Server programming is probably best known and, in this regard, more reliable. Having the client receive raw data and format in via JavaScript moves a lot of work away from the server. Among other things, this is also a green factor and potentially a way to save power. Downloading JSON instead of HTML is generally faster but force developers to design web pages in a totally different way. For the most part you need a client-side data-binding engine whether MustacheJS (see http://www.simple-talk.com/dotnet/.net-framework/quick-and-dirty-web-data-binding), KnockoutJS or some modules of AngularJS.

In the end, it is matter of preference whether you want to have HTTP endpoints that return preformatted HTML or plain JSON data to format via JavaScript. A more important decision for live web pages is the choice of mechanism that triggers the page refresh.

On the Way to Long Polling and ASP.NET SignalR

In the previous code snippet, I used a dummy timer that insists on queuing a call to the specified HTTP endpoint every specified number of milliseconds. This may generate quite a bit of traffic. You can certainly fine-tune the amount of traffic acting on the length of the interval, but that has to be mediated with the frequency at which you need to show fresh data, if any. For example, you’re providing live sports coverage that provides the current score for a sport like tennis in which the score changes in a matter of seconds. A good value to set the timer might be 30 or 40 seconds. It can be slightly shorter if you’re live-scoring several matches that are in progress, and it can be slightly longer if you’re following a single match. Yet it means that you’ll having a call made to the server every 30 or 40 seconds from any of hundreds or thousands or more of the clients connected.

ASP.NET SignalR is a framework that helps to minimize the impact on the server of this kind of operation in a way that is completely transparent to developers, SignalR uses web sockets to connect to the server if the browser supports them; otherwise it switches to long polling. The effect is the same but the impact on the server is reduced to the absolute minimum that is possible. Let’s see how to configure ASP.NET SignalR.

Configuration of SignalR

The first step towards using SignalR is to install the package from Nuget. You get a few files, some JavaScript files and some binaries. One of the binaries is the OWIN library that is used to start and configure SignalR. Firstly, you must have the following file in the project, named startup.cs.

SignalR has a client and a server part. The client part consists of a couple of JavaScript functions-one to start up the listener for server-side changes and one to notify the listener of server-side changes. The client-side part is served as a jQuery plugin. In the web page that is expected to display live data, you reference the SignalR script file.

Next, you add the following script block to the same HTML view.

The code snippet contains a few references that need be further explained, most notably the hub object. The $.connection object is the entry point in the SignalR jQuery plugin and exposes a reference to start the client infrastructure in charge of listening from changes from the server. The $.connection.hub object is the wrapper for the communication infrastructure that uses long polling or web sockets as appropriate. By calling the method start, you start the listening process. You also have a chance to perform some initialization tasks, such as updating the user interface, but that’s entirely optional.

SignalR Hubs

A lot more interesting is the $.connection.yourAppHub expression you also find in the preceding JavaScript code snippet. That refers to the client-side corresponding endpoint for the server-side SignalR processor. Put another way, once you start the connection your client code will be called back from the server whenever the server detects any relevant action to be notified to the client. Any time the server code performs a task that changes the state of the system, it might want to call back the client and pass specific information.

The callback takes place through a Hub class you define on the server. Here’s an example:

The server-side hub class can have as many methods as you wish, typically one per each update scenario you want to be reflected on the client. To notify the clients of updates, the server code just calls one of the methods on the hub class, or one of the hub classes you may have. Have a careful look at the following line:

Where is the refreshPage method coming from? That’s the name of the JavaScript method that will react to the server notification. In addition, the name of the client-side hub matches the name of the server hub-yourAppHub.

There’s one more piece that’s still missing. Where’s the code that makes it possible to find an object called yourAppHub on the SignalR plugin and where’s the code that ensures that the JavaScript object has the same programming interface as server hub? It’s all in the following script endpoint you need to have on the HTML view along with the reference to the SignalR jQuery plugin.

That’s a fixed HTTP endpoint; and it will inject auto-generated JavaScript code in your page. The code behind the endpoint will look at your server hub classes and generate any matching JavaScript code and inject it in your DOM.

Moving data around

If necessary, the server hub can pass data around to the client. Whenever any of the server tasks perform something that must be notified to the client, all they do is to invoke a hub method.

Nothing prevents you from adding data to the prototype of the Refresh method. If you do, the data is serialized to JSON and handed over to the JavaScript hub client.

If incoming data is made of a few sparse values updating the DOM may be quite easy. If not, say it’s a list of objects, it may then require a HTML template. This in turn involves using a templating framework such as AngularJS, KnockoutJS or even Mustache. As an alternative, you can just tell the JavaScript client code to request an HTML update from the server. This is what the following code, already shown above, actually does:

Assuming an ASP.NET MVC application, the method Update on the Live controller returns a fresh chunk of HTML that will be inserted in a DIV container with jQuery. In this case, your HTML views remain classic HTML views with no need of having client-side data binding involved. It goes without saying that if instead you just see value in using client-side data binding then SignalR is definitely your best choice.

Summary

The old pattern of polling a server shared resource to see if anything has changed since last time is one that always works. It might be debatable about how effectively it works, but for sure it works. Even if polling works for you today, you might want to look into an alternative that may only give you better performance and put less pressure on the server. This is ASP.NET SignalR, a server-side framework with a jQuery plugin to bind client page refreshes to commands coming from the server. Web sockets are used to implement this push mechanism and if web sockets are not supported by the browser then plain polling is used in a way that is completely transparent to the developer.