virtual application tiles with male pointing at one

SignalR in ASP.NET Applications

Use the handy SignalR library to build real-time communication into your web applications

Related: Real-Time Communications with SignalR

SignalR is a .NET real-time communication framework primarily focused on web applications. SignalR provides an abstraction to a continuous, persistent, two-way communication tunnel between clients and the server, providing real-time or near real-time updates between the server and any number of potentially disparate clients.

SignalR uses both server and client components to perform this communication. Web applications are the most common use case, relying on JavaScript and jQuery to perform the operation. (Windows desktop, Windows Store, Silverlight, and Windows Phone applications are supported as clients to some degree.) In this article, I will give you a brief overview of SignalR architecture and then provide some examples of how to work with SignalR in your ASP.NET applications.

Communication

SignalR is built on top of several different communication protocols and will gracefully fall back to other technologies depending on the capabilities of the client platform or browser. It is important to note that SignalR is an abstraction on top of the (conceptually separate) communication protocols it uses. Should the SignalR framework be updated in the future to use a different protocol, code and modules calling SignalR components should not need to be reworked (unless those modules call the underlying communication protocol directly, of course). Because of this, disparate clients can run the same code that uses SignalR even if their connection capabilities are vastly different.

Related: ASP.NET SignalR: More than Just Chat

The first protocol that SignalR attempts to use for communication is WebSockets, an emerging web standard. This protocol is supported in all major browsers and mobile platforms, making its use incredibly valuable to new projects designed around web services.

In the cases where WebSockets is not supported, SignalR will fall back to using the following techniques in this order:

  • server-sent events (on supported platforms)
  • Forever Frame (on Internet Explorer 8 and later)
  • long polling (on all supported platforms and browsers)

This, in theory, makes SignalR resilient in handling disparate client connections, providing a wide area of potential support with minimal developer effort.

Hosting

SignalR 2 formalizes the self-hosting capability of the framework by relying on Microsoft's Open Web Interface for .NET (OWIN) technology to serve as a base. SignalR can be integrated into ASP.NET applications as well as into self-hosted solutions using OWIN.

Working with SignalR

SignalR is available as a NuGet package. To install SignalR, you simply add it to a solution in Visual Studio, as shown in Figure 1. Note that SignalR 2 is available in ASP.NET and Web Tools for Visual Studio 2013 and therefore requires Visual Studio 2013 (Visual Studio Express for Web or any of the complete Visual Studio versions).

Figure 1: Installing SignalR in Visual Studio
Figure 1: Installing SignalR in Visual Studio

The SignalR JavaScript library for use in web projects has a dependency on jQuery and is installed with SignalR. When SignalR is installed, it adds several references and .js files to the project, as shown in Figure 2.

Figure 2: References and .js Files Added to a Visual Studio Project After SignalR Is Installed
Figure 2: References and .js Files Added to a Visual Studio Project After SignalR Is Installed

Initializing SignalR

SignalR needs to be integrated into the application's startup process.

Figure 3: Adding an OWIN Startup Class to a Project
Figure 3: Adding an OWIN Startup Class to a Project

The OWIN integration makes it easy to do this. You simply add an OWIN Startup class to the project, as shown in Figure 3, and then add a command to map SignalR and its components, as shown in Listing 1.

using Microsoft.Owin;
using Owin;

[assembly: OwinStartup(typeof(SignalR2Demo.Startup))]
namespace SignalR2Chat
{
    public class Startup
    {
    public void Configuration(IAppBuilder app)
    {
        app.MapSignalR();
    }
    }
}

On the server, SignalR uses hubs to communicate with clients (both incoming and outgoing). These hubs are detected at runtime and do not need to be specifically registered. (That's what app.MapSignalR() is for.)

Creating Hubs

Developer-defined hubs inherit from a Hub class and are named by convention (though this can be overridden). Following are some examples of hub definitions. Note that without the HubName attribute, hubs are interpreted to be named by their class name.

public class ChatHub : Hub { ... }
[HubName("stockTickerMini")]
public class StockTickerHub : Hub { ... }

When called by a client, the clients use the mapped hub name. The two previous examples would be referenced, respectively, as "chatHub" and "stockTickerMini" in a JavaScript client.

Calling Clients

Hubs can communicate with clients via a Clients property that allows for selective or broadcast communication with active clients. Clients can be selected by groups or by specific connection IDs. Sending messages to clients lets your code leverage .NET's dynamic keyword to allow for runtime definitions of methods without having to jump through hoops. Here are some examples of calls to clients:

Clients.All.broadcastMessage(name, message);

var callingClient = Context.ConnectionId;
Clients.AllExcept(callingClient).move(state);

Clients.All.updateStocks(stocks);

Note that the actual method calls on the clients are dynamically generated and matched to corresponding client methods at runtime, when the calls are made. These are not defined statically—thus, developers must be careful with spelling and capitalization.

It is also important to note that hubs are transient. That is, they are created when messages arrive and are disposed after handling the message. They are therefore stateless, and so any state must be maintained outside of the hub. In the earlier StockTickerHub example, the hub's state is kept in another object, StockTicker, exposed as a singleton. The hub is created with the instance reference, used, then disposed of. The hub is defined as shown in Listing 2.

public class StockTickerHub : Hub
{
    private readonly StockTicker _stockTicker;

public StockTickerHub() : this(StockTicker.Instance)
    {
    }

public StockTickerHub(StockTicker stockTicker)
    {
    _stockTicker = stockTicker;
    }

public IEnumerable GetAllStocks()
    {
    return _stockTicker.GetAllStocks();
    }
}

In this case, StockTicker maintains a list of stocks that might change over time. Clients will periodically request updates by calling the hub's GetAllStocks method (note how it returns .NET objects natively; these are serialized by SignalR and passed back to the client automatically). The hub, because it has no knowledge of state, must fetch this information using the StockTicker instance it receives in its default constructor (which is called when the hub is created by SignalR when a message comes in). In this way, hubs must necessarily be decoupled from the source of any dynamic or changing data.

Registering Clients

Clients live and die differently than a server does, though their specific processes are similar. When a client comes up, it must register with SignalR to send and receive messages from the hubs.

Most SignalR clients use the SignalR JavaScript library, which has a dependency on jQuery. For web apps that use SignalR, they must reference two specific JavaScript files and a dynamic location generated by SignalR at runtime:



The specific files obviously vary depending on the installed version of both jQuery and SignalR. The final line refers to a location that SignalR injects into the site when it is run and is required to reference the hubs.

Related: Real-Time Communications with SignalR

When the app loads, SignalR needs to be started using the following code:

$.connection.hub.start().done(function () {
    // initialization logic that has to occur after SignalR startup
});

The function done is run once SignalR is successfully initialized.

Hubs are referenced using the following code:

var ticker = $.connection.stockTickerMini;

Client functions that the hubs listen for are created like this:

ticker.client.updateStockPrice = function (stock) {
    // handle incoming data
};

And clients can call hubs like this:

ticker.server.getAllStocks().done(function (stocks) {
    // handle the result
});

Note again the importance of correct spelling, particularly on the JavaScript side.

Get Connected with SignalR

I encourage you to explore using SignalR to add real-time web functionality to your applications. I hope you'll find, as I have, that this handy new library makes it easier for you to build connected apps using ASP.NET.

Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish