October 2014

Volume 29 Number 10


Modern Apps : Use SignalR to Build Modern Apps

Rachel Appel

Rachel AppelWith widespread access to broadband Internet and wireless devices, there’s considerable demand for real-time apps. Popular sites such as Facebook and Twitter, multiplayer games and collaborative business apps have the best UX when they’re live, real-time apps. Many other types of apps are great candidates for real-time experiences, such as stock and finance apps, auctions, sales dashboards, e-commerce and educational apps. Even Web sites and apps where live data isn’t a necessity can benefit from real-time, full duplex communications with SignalR.

What’s SignalR and Why Should I Use It?

SignalR is a set of server and client libraries that facilitate simple, real-time, two-way communications between server and client. Not only can the client initiate contact with the server, as is the case in Web development, but the server can also contact the client. Those aren’t just simple HTTP responses, either. These are actual method calls from server to client, like push technology. Clients can even contact other clients through the SignalR server-side component. All this is possible because SignalR creates a persistent connection between the server and client.

Everyone wants to create modern software—and it doesn’t get any more modern than full duplex communications. There are several reasons to use SignalR. Its ease of use for writing Web sites and apps is one good reason. Another is if you need live communication in your software. In those instances, SignalR is the way to go. You could do it yourself using any number of techniques, such as WebSockets or AJAX polling. However, you’d have to rewrite all the groundwork the SignalR team has already done. This groundwork is fairly expansive and includes several key features:

  • Transport negotiation: SignalR detects the best transport to get as close to real-time communications as possible. It uses WebSockets by default, as that’s the fastest and most modern way to write real-time Web apps. Automatic transport management is behind the idea of real-time communication in SignalR. It negotiates a transport for each client as it connects.
  • SignalR server host: You can choose between lightweight self-hosting anywhere, including non-Microsoft platforms, or hook SignalR into the IIS pipeline.
  • Client-side libraries: Including JavaScript, the Microsoft .NET Framework and Windows Store libraries.
  • JavaScript proxy: This provides a way to call methods in remote locations in JavaScript, while developing as if all code is running in the same process on the same machine.
  • Security: SignalR hooks into existing ASP.NET security models, and supports many popular third-party security providers such as Microsoft Live, OpenAuth, Google, Facebook and Twitter.

Web developers traditionally write code according to the request/response model of HTTP. There’s nothing inherently bad with this, but it lacks the primary benefit of SignalR—a persistent connection between server and client. In HTTP, you make a request, get a response and then you’re done. In a real-time scenario, the pipeline stays open between the server and client. This lets you create richer and better UXes that feel alive and connected.

In SignalR, there are two layers of abstraction over the low-level transports—hubs and persistent connections. This article will cover just hubs for the sake of brevity. Hubs are the higher-level API that’s the “incredibly simple” part of SignalR. Persistent connections take more time and effort to code, and SignalR uses them as the basis for hubs. You’ll generally use hubs for most of your activities, unless you have good reasons to do otherwise.

Get Started with SignalR in Windows Apps

Like many other .NET libraries, SignalR comes as a NuGet package. You can install it with the NuGet Package Manager or the Package Manager Console. Both are features of Visual Studio 2012 and Visual Studio 2013. There are several different SignalR packages available from Microsoft, including:

  • Microsoft ASP.NET SignalR: The base package that installs Core and Web components with the JavaScript client
  • Microsoft ASP.NET SignalR Core Components: Hosting and core libraries
  • Microsoft ASP.NET SignalR System.Web: SignalR for ASP.NET
  • Microsoft ASP.NET SignalR JavaScript Client: JavaScript client libraries for HTML apps
  • Microsoft ASP.NET SignalR .NET Client: Client libraries for other Windows platform apps

When you install the Microsoft ASP.NET SignalR package in any of your ASP.NET projects (Web Forms or MVC), SignalR installs the dependencies in each of the packages listed except the .NET Client. The .NET Client is for Windows 8 and Windows Phone XAML apps, Windows Presentation Foundation (WPF), Windows Forms and Console apps. There are more SignalR packages in the NuGet Package Manager from both Microsoft and third parties. These cover just about everything including, self-hosting, scaling, dependency injection and MongoDB support.

After installation, there are no web.config settings to adjust. However, you must add a small snippet of startup code to indicate to ASP.NET that you’ll be inserting SignalR into its pipeline:

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

You can add this Startup class to a .cs file in the App_Start folder. Some of the ASP.NET project templates already include a Startup class for ASP.NET Forms Authentication. If this is the case, just add the Configuration method to that class instead. Once you do this, you can move onto writing real-time code.

This Startup class is an Open Web Interface for .NET (OWIN) startup. That means it adheres to the new OWIN specifications. OWIN is a standard much like the standards governed by the Worldwide Web Consortium (W3C). Microsoft has implemented OWIN in a project called Katana. That’s the engine behind SignalR that works in tandem with IIS, or as a self-host to facilitate two-way communications. As a SignalR developer using hubs, you won’t need to know much more than that about OWIN or Katana. SignalR abstracts all that away so you can focus on solving your business problems with SignalR.

The Server Side of SignalR Hubs

Hubs are the communications core of SignalR. They receive incoming requests and push messages to clients, either from the hub itself or on behalf of another client. You can consider a hub in SignalR to be like a hub and spoke of a wheel.

The hub is just a gatekeeper for the messaging. While they’re at the center of the action, hubs are just classes that inherit from the Microsoft.AspNet.SignalR.Hub class. The Hub class, in turn, imple­ments the IHub interface of the Microsoft.AspNet.SignalR.Hubs namespace. The IHub interface defines three events: OnConnected, OnDisconnected and OnReconnected. It also defines three properties: Clients, Context and Groups. These are common tasks or information related to each real-time connection to the hub.

The client calls public methods on the hub, which means the code looks like a Web Service call. However, SignalR hubs can initiate contact with clients that have registered with them. You don’t normally program with this kind of behavior in mind, as you’d normally use the traditional request/response model.

This can happen because of the Clients property that represents a collection of all the connected clients. Through the Clients property, you can access a single client or multiple clients regardless of their platform. For example, an iOS client can send a message to a Windows client through the hub as the hub communicates with the Windows client on the iOS client’s behalf and vice versa.

To see the hub in action, I’ll examine a sample app called VoteR that displays a series of items and lets users vote for their favorite. At the app’s core, there’s a VoteHub class. This is the hub that tallies the votes users have cast for each item. It then notifies clients of the updated numbers. Figure 1 shows an example of the VoteHub class.

Figure 1 The VoteHub Class Tallies Votes

public class VoteHub : Hub
{
  private static List<Item> VoteItems = new List<Item>();
  private static VoteRContext db = new VoteRContext();
  public void Vote(int id)
  {  
    var votes = AddVote(id);
    Clients.All.updateVoteResults(id, votes);
  }
  private static Item AddVote(int id) {
    var voteItem = VoteItems.Find(v => v.Id == id);       
    if (voteItem != null)
    {
      voteItem.Votes++;
      return voteItem;
    }
    else
    {
      var item = db.Items.Find(id);
      item.Votes++;
      VoteItems.Add(item);
      return item;  
    }       
  }
  public override Task OnConnected()
  {       
    Clients.Caller.joinVoting(VoteItems.ToList());
    return base.OnConnected();
  }
}

The two methods to investigate in Figure 1 are the Vote and Add­Vote methods. The Vote method is what the clients call (covered in the next section). The app then calls the private AddVote method, which does the actual vote counting. It does so by checking to see if items are already in the VoteItems list. If they are, it will update them. If not, the first time a user votes for them, AddVote will add that item. A static List<Vote> is an easy way to store simple global information such as this without a database.

The Vote method in Figure 1 contains an interesting line of code after its call to AddVote:

Clients.All.updateVoteResults(id, votes);

In SignalR, you’ll use the Clients property to access and call code on the client. From the Clients property, you can target the clients you want to access. Sometimes it’s all clients, such as when a new vote happens. Sometimes it’s only one client, such as when a user first connects. Using naming conventions lets SignalR match the server call with the code on the client to run. This is the first time in the history of ASP.NET that you can use dynamic properties to call code on the client.

As you might imagine, because the VoteHub needs to track votes, it makes sense that there’s an event like OnConnected. The OnConnected event lets you capture new, incoming connections. A likely scenario is to trap the connection’s id through the ConnectionId property of the Context object.

In the case of the VoteR app, in Figure 1 it’s cycling through the three items in the VoteHub List<Item> object and notifying the client how many votes each item has via the Clients.caller property. This way, newly connected clients immediately have the total number of votes for each item upon joining the party.

There are many other ways to communicate between server and client. The Clients property of the Hub class exposes the many various ways we can access client code, as outlined in Figure 2.

Figure 2 Various Ways to Communicate from the Server to the Client

// Call method on all clients
Clients.All.clientSideMethod(args, args, ...);
// Call method on specific client       
Clients.Client(Context.ConnectionId). clientSideMethod(args, args, ...);
// Call a method on a list of specific connections
Clients.Clients(ConnectionId1, ConnectionId1, ...).clientSideMethod(args, args, ...);
// Call method on calling connection
Clients.Caller.clientSideMethod(args, args, ...);
// Call method on all clients but the caller
Clients.Others. clientSideMethod(args, args, ...);
// Call method on all in the group except a few select connections
Clients.AllExcept(connectionId1, connectionId2).clientSideMethod(args, args, ...);
// Call method on groups of connections
Clients.Group(groupName).clientSideMethod(args, args, ...);
// Call method on connected clients in a specified group
Clients.Groups(GroupIds).clientSideMethod(args, args, ...);
// Call method on other connected clients in a specified group
Clients.OthersInGroup(groupName).clientSideMethod(args, args, ...);

In Figure 2, the clientSideMethod is defined on the client the server calls. In the next section, you’ll learn how to define these methods on the client. As you can see, the dynamic nature of the Clients property lets you write code for a wide range of server-to-­client-communication scenarios.

The Client Side of SignalR: JavaScript and .NET Clients

You can build real-time apps on any platform with SignalR. Out of the box, you can use the SignalR JavaScript client for all things Web and HTML client apps, including WinJS apps. Plain HTML and JavaScript are widely supported languages. For the .NET folks, Microsoft has released a .NET client for both Windows and desktop apps. Like the core components, you install either the JavaScript or .NET Client from NuGet, depending on the type of your project. Because JavaScript is just JavaScript, you can download the scripts from github.com/SignalR/SignalR, and add <script> tags to your page, as opposed to referencing .dll files, as shown here:

<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/jquery.signalR-2.0.3.js"></script>
<script src="~/signalr/hubs"></script>

The order of the script references is important. You must load jQuery first because SignalR depends on it. Next in line is the SignalR client. The last one is the SignalR proxy. SignalR dynamically generates a proxy at run time and drops it off at /signalr/hubs. This proxy is what lets you write code on both the client and server, yet have it behave as if it’s all in the same location.

The VoteR app’s client script defines methods to receive calls from the server, as well as ordinary methods and event wire-ups. In Figure 3, the very first line of code traps a variable called voteHub. This is a direct line to an instance of the VoteHub class. SignalR creates an instance of the hub for each client that connects. The client starts the connection with a call to $.conne­ction.hub.start that returns a promise. This means the code within won’t run until it’s complete. In this case, it’s a call to the Vote method on the server inside the voting button’s click event. As you can see, it passes the item id for which the user is voting to the server. Then the server does the work outlined in Figure 1.

Figure 3 JavaScript Client Code

$(function () {
  var voteHub = $.connection.voteHub;
  $.connection.hub.start().done(function () {
    $("button").click(function () {
      voteHub.server.vote(this.id);
        });
  });
  voteHub.client.updateVoteResults = function (id, vote) {
    // Update UI to show each item and how many votes it has
    }
  voteHub.client.joinVoting = function (votes) {
    // Cycle through votes to display current information
    // about each item to newcomer
  }   
});

At this point, you might think there are typos in Figure 3. That’s because naming the VoteHub class and Vote method is inconsistent between server and client. That’s not a typo, but rather a SignalR convention. In JavaScript clients, calls to hub.server.methodName go in camelCase by default. It’s easy enough to change this behavior by attaching the HubName attribute to the Hub class with the exact capitalization you want. The HubName attribute looks like this: HubName(“VoteHub”).

The two most interesting pieces of code in Figure 3 are the voteHub.client.updateVoteResults and voteHub.client.joinVoting blocks. As their signatures indicate, both methods are members of the Client property of the VoteHub on the server. Reflecting back on Figure 1, the client-side voteHub.client.updateVoteResults method from Figure 3 aligns with the Clients.All.update­VoteResults(id, votes) call from Figure 1. Figure 4 shows the relationship between the server and client code.

The Relationship Between Hub and Client Method Calls
Figure 4 The Relationship Between Hub and Client Method Calls

Now, it’s time to examine the .NET client. Figure 5 shows some code that makes a connection from a Windows Store XAML app using C#. This could just as easily be a Windows Phone app, as the code is identical. It starts by creating a connection to the SignalR pipeline. Then it goes on to create the proxy.

What you see in Figure 5 that you won’t normally see in the JavaScript client is the HTTP path to the SignalR pipeline passed into the HubConnection constructor. Unlike the JavaScript client, it’s slightly less automatic. You must instantiate a HubConnection and call CreateHubProxy to create the proxy.

Figure 5 Windows Store C# Client Code to Vote in VoteR

async private Task startConnection()
{
  var hubConnection = new HubConnection("https://localhost:25024/signalr");
  IHubProxy hubProxy = hubConnection.CreateHubProxy("VoteHub");
  var context = SynchronizationContext.Current;
  hubProxy.On<string, string>("updateVoteResults", (id, votes) =>
    context.Post(delegate {
  // Update UI
); }, null));                        
  await hubConnection.Start();
  await hubProxy.Invoke("vote", "rachel", 
    Convert.ToDecimal(itemId.Text));
}

Notice in Figure 5 there’s an assignment that obtains a synchronization context. You wrap the client code the server calls with this context object. Then you call its Post method and pass a delegate. Delegates in C# are the same as inline anonymous functions in JavaScript.

After starting the hub’s connection, you can call its proxy’s Invoke method to vote on an item. Using the await keyword causes it to perform those actions asynchronously. You can find the complete source for the VoteR demo application at: github.com/rachelappel/VoteR.

SignalR Deployment: Server and Client

Because SignalR is ASP.NET, you must deploy to an environment with the .NET Framework 4.5 or later, unless you self-host. In an ASP.NET project, SignalR is just a set of libraries. It goes along with the other libraries when it’s time to deploy.

If you think the rest of SignalR is easy, wait until you try to deploy to Microsoft Azure. Using Azure makes the deployment process especially stress-free. This also deploys both the SignalR server component and at least one HTML client to a Web server. Of course, you must publish any Windows Store or Windows Phone apps to the app store, and desktop apps to desktops through their appropriate channels.

Those with any ASP.NET projects can choose Publish from the Visual Studio Build menu to start the deployment to Azure. If you’re using Visual Studio 2013, you can just follow the prompts. You’ll only need to enter your credentials and choose the database and Web site name.

In Visual Studio 2012, it’s a similar set of prompts. During deployment, you can choose to create a new Azure Web site or select an existing one. If it’s an existing site, log in to the Azure Portal, navigate to the Configuration tab, and find and turn on WebSockets. You must do this with a new Web site, as well, but Visual Studio will create and launch the site first, which will cause an error. Again, just log in and turn on WebSockets. That’s the important thing. It’s a good idea to stop and start any Web sites after a configuration change.

Wrapping Up

SignalR really is simple, real-time programming. While it’s an ASP.NET product, it’s cross-platform in that you can write Windows Store, iOS and Android apps with an ASP.NET server component. You can also self-host on non-Microsoft OSes. This makes SignalR flexible, as well as simple and efficient. Another great thing about SignalR is that you don’t even need to have real-time functionality as a requirement. Use it going forward and join the many who have already adopted the real-time programming paradigm.


Rachel Appel is a consultant, author, mentor and former Microsoft employee with more than 20 years of experience in the IT industry. She speaks at top industry conferences such as Visual Studio Live!, DevConnections, MIX and more. Her expertise lies within developing solutions that align business and technology focusing on the Microsoft dev stack and open Web. For more about Appel, visit her Web site at rachelappel.com.

Thanks to the following Microsoft technical expert for reviewing this article: Frank La Vigne