Posts Tagged 'SignalR'

Having the Server Update the Client with SignalR: A Case Study, Part II

In a previous post, I started a case study, looking at an application where it made sense to use Microsoft’s new SignalR technology. The application that I chose is a sales order system that allows users to purchase products. In addition (and here’s where the client-side callback support that SignalR provides becomes useful), users can mark a sales order as “to be expedited.” An “expedited” sales order could go through all of the processing that leads to it being shipped in a few minutes. In that scenario, the client might be willing to stay online and get updates as the order changed progressed through the process. To support that, I wrote some JavaScript code to have the Web page connect to a SignalR message hub. The hub would send out messages about the status of an order as the hub received updates from other, non-Web clients that were processing the order. When a user marked an order as “to be expedited”, my JavaScript code registered with the hub, passing the ID of the sales order the page was interested in. I used SignalR’s support for messaging groups to organize requests in groups by sales order number–the message hub could send a single update to the group for a salesorder and have that message delivered to all of the interested parties.

In this post, I’m going to look at the .NET clients that, while processing a sales order, will also log onto the message hub and send updates to the hub for processing.

One caveat: As I’m writing this, SignalR is still in beta. It’s possible that things will change before SignalR is released, invalidating what I say here. It’s also possible that SignalR will go the way of Microsoft’s Upshot and never get released at all.

Sending Updates

I could have the .NET clients that will be processing the sales order connect to the message hub and get a list of registered sales orders. However, that’s not necessary in this case because expedited sales order have a field indicated whether or not they’re being expedited. As a result, when a client is processing a sales order it will check the Expedite flag on the order and connect to the message hub.

The first step in creating a .NET client that can work with SignalR is, in Visual Studio, to use NuGet to add the Microsoft ASP.NET SignalR Client and the Json.net packages to the project. That’s true even if, as I am, you’re creating a non-ASP.NET client (I’m building my client-side code in WPF). Once that package is in place (and an Imports or using statement added for the Microsoft.AspNet.SignalR.Client.Hubs namespace) you can write the code to open a connection to the message hub.

With the Web client, I was obliged to start the connection with the hub and keep the connection open so that my Web client could receive messages from the hub at any time. However, this .NET client is only sending messages to the hub and not receiving them. Since there is a cost associated with every connection maintained at the server, if there are a lot of .NET clients then it may make sense to start the connection from these clients only when there’s some information to send. For this case, study, however, I’m going to assume that there is only a single program that processes sales order and so I’ll have that program start the connection as soon as the program starts. This means that I’ll be starting the connection in one method (Window_Load, probably) and using the connection in other methods–I’ll need to declare both the hub and connection at the class level:

Class MainWindow
  Private conn As HubConnection
  Private hub As IHubProxy

To open the connection to the message hub, I create a HubConnection object, passing the URL for the server that my hub is executing on. After that, I create the hub by passing the name of my hub’s class (SalesOrderNotifications, in my case) to the HubConnection’s CreateHubProxy method. I then call the HubConnection’s Start method. This is an asynchronous method but, since there’s not much point in continuing if I don’t have the connection started, I use the Await keyword to wait for the Start method to complete. To support the Await keyword, I put the code in a separate method that I’ll declare as Async and call the method from the Window_Load event of my WPF client:

Private Async Sub InitializeHub()
  conn = New HubConnection("http://localhost:49206/")
  hub = conn.CreateHubProxy("SalesOrderNotifications")

  Await conn.Start
End Sub

In some other method, I’ll call the method on my message hub that send out an update message as the sales order’s status changes. For that I use the hub’s Invoke method, passing the name of the method on the message hub I want to call along with any parameters that method requires. My method on the message hub is called UpdateSalesOrderStatus and must be passed the SalesOrder Id and a SalesOrder status. The Invoke method is also asynchronous but, since nothing in my client depends on the method, I’ll use it in “fire and forget” mode: call the method let it complete in the background. That code looks like this:

Public Sub TalkToHub(SalesOrderID As String, Status As SalesOrderStatus)
  hub.Invoke("UpdateSalesOrderStatus", SalesOrderID, Status)
End Sub

When a client gets tired of receiving messages, they can call the stop method on their connection connection’s hub property which will not only break the connection but will also remove them from any groups they are part of.

And that’s it: I have a message hub that accepts clients and routes messages between them. It’s a very cool technology.

Peter Vogel

Having the Server Update the Client with SignalR: A Case Study, Part I

In earlier posts, I described how to set up a SignalR server-side hub that can receive message from and, more importantly, send messages to the client, how to create a JavaScript client that could send and receive messages from that hub, and how to send and receive messages from  .NET (i.e. non-JavaScript) clients. As I noted in those articles, these are things that any Web Service can do.However, with an ordinary Web Service, the server can only send a message as part of response to a request from the client. SignalR lets the server send messages to the client whenever the server has information to share with the client and have the client receive the messages immediately (at least, with up-to-date browsers; with older browsers SignalR automatically falls back to repeatedly checking the server for updates (polling).

But all of those posts used simple “proof of technology” examples (I was only passing text between the clients and the server, for instance). This post will do something more realistic (not “realistic,” just “more realistic”) with the tools developed earlier. I’ll also introduce some SignalR functionality that makes it easy to send messages to groups of users.

A Sales Order Status Notification System

For my case study, I’ll assume a Web-based Ajax-enabled sales order system. While it would be possible to create all the Web Services required by this application (all the CRUD operations on sales orders, for instance) using SignalR for those operations doesn’t make a lot of sense. A SignalR hub requires a persistent connection between the client and the hub so that the hub can send messages to the clients at will (in fact, the technology that I’ve used in these posts is a wrapper for a more low-level object called PersistentConnection)–those connections have to start piling up at the server and should be used…judiciously. While I haven’t done any performance testing a hub certainly appears to be a singleton object which suggests that it could form a bottleneck within an application. And, besides, the CRUD operations don’t require what SignalR provides: immediate updates from the server when something changes at the server. SignalR shouldn’t be used indiscriminately but only where it adds value.

So where, in this application, would using SignalR add value? While most sales orders are processed in a cycle that takes several days, the application lets customers ask for “expedited processing” which causes the order to be placed and the product shipped (or a service team dispatched) in a few seconds–one or two minutes at the most. In this scenario, the user can leave their client up and see updates as the sales order progresses through the processing cycle.

To support that, the application register expedited orders with a SignalR hub. As applications elsewhere in the company process the sales orders they will send messages to the same hub that all the other clients have connected to. The hub will then update the interested client (or clients) in the sales order’s progress

Creating the Infrastructure

I’ll start by defining a class that I can use to pass sales order status around and an enumerated value for the various statuses that an order can go through:

Public Class SalesOrderStatusUpdate
    Public Property ID As String
    Public Property Status As SalesOrderStatus
End Class

Public Enum SalesOrderStatus
    Started
    InProcess
    FinalProcessing
    ProductOrServiceTeamDispatched
End Enum

My next step is to define the hub with a method that allows clients to tell the hub which sales order(s) the clients are interested in tracking. In this organization it’s possible that multiple clients may want to track a single order so, to support that, I’ll take advantage of SignalR’s Groups functionality. SignalR Groups allow you to create named collections of clients that you can send messages to (without sending messages to clients in other groups). Clients are added to groups by passing the group name (which you make up) and the client’s ConnectionId (which can be retrieved through the hub’s Context property).

This is the method that the client will call, passing a sales order Id, to register the client’s interest in a sales order. The code adds the client to a group with name of the sales order Id. The code then sends a return message to the caller the using the Clients Caller property (this code assumes that the client has defined a function called acknowledgeRegister to accept that message):

Imports System
Imports System.Web
Imports Microsoft.AspNet.SignalR

Public Class SalesOrderNotifications
    Inherits Hub

    Public Sub RegisterForSalesOrderStatusUpdate(ID As String)
        Me.Groups.Add(Me.Context.ConnectionId, ID)
        Me.Clients.Caller.AcknowledgeRegister("Registered")
    End Sub

The next step is to define a method that other applications can call to provide information about the sales order’s status. This method will accept two parameters (a sales order’s Id and the current status of the sales order), create a SalesOrderStatusUpdate object with those values, and then send that SalesOrderStatusUpdate object to all the members of the group with the same name as the sales order Id. Sending that message is especially easy: Just use the Clients’ Group method, passing the group name.

This code does all of that (and assumes that clients have implemented a method called GetSalesOrderStatusUpdate to receive the message):

Public Sub UpdateSalesOrderStatus(ID As String, Status As SalesOrderStatus)
    Dim sosu As New SalesOrderStatusUpdate With {.ID = ID, .Status = Status}
    Me.Clients.Group(ID).ReceiveSalesOrderStatusUpdate(sosu)
End Sub

Also, on the server, I need to register my SignalR hubs with this line of code (in an ASP.NET MVC application, I’d include this code with the rest of my routing commands; in an ASP.NET application, I would put it in my Global.asax file’s Application_Start method):

RouteTable.Routes.MapHubs()

Creating the Client

On the client, I need to open a connection to my server when the user requests the “Expedited Order” option. First I need a textbox to hold the sales order id and a checkbox to let the user indicate that the order is to be expedited:

<asp:TextBox ID="salesOrderIdTxt" runat="server" />
<asp:CheckBox ID="expeditedOrderChk" runat="server" Text="Expedite Order" />

When the checkbox’s change event fires I need to see if the box has been checked or unchecked. If the box has been checked, I will create a connection to my SalesOrderNotifications hub:

<script type="text/javascript">
 var conn;
$(function () 
 {
   $("#expeditedOrderChk").change(function () 
       {
         if (this.checked) 
           {
            conn = $.connection.salesOrderNotifications;

The next step is to supply client-side JavaScript functions to be executed when the hub either calls the  acknowledgeRegister or receiveSalesOrderStatusUpdate methods at the server:

            conn.client.acknowledgeRegister = function (message) 
                    {
                     $('#messages').append(message);
                    };
            conn.client.receiveSalesOrderStatusUpdate = function (sosu) 
                    {
                      $('#messages').append(sosu.Id + ": " + sosu.status);
                    };

Now, when the hub calls the aknowledgeRegister method passing a string (in the server-side RegisterForSalesOrderStatusUpdate method) the JavaScript code here will add that string to the messages element on the page; similarly when the hub calls the recieveSalesOrderStatusUpdate method (as part of the hub’s UpdateSalesOrderStatus method) the Id and status properties will be pulled from the object and added to the messages element.

I’m now ready to start the connection. This code, after starting the connection, retrieves the sales order id from the page and passes it to the hub using the registerForSalesOrderStatusUpdate method to indicate that I want to receive messages about the sales order (i.e. to have me added to the group for this sales order Id):

            $.connection.hub.start().done(function () 
                    {
                     var soId = $("#salesOrderIdtxt").val();
                     conn.server.registerForSalesOrderStatusUpdate(soId);
                    });
           }
       });
 });

In my next post, I’ll look at the applications that will send sales order updates to the hub and allow clients to deregister from the hub.

Astute readers will recognize that what I’m implementing here is a variation on the Observer pattern. In the Observer pattern, an object maintains a list of clients that are to be notified when something happens. Clients register with the observer to be added (or removed) from this list. In the basic Observer pattern, all the clients are simply notified that “something has happened”  at the object. To find out what has actually happened, the clients have to request information from the object to find out exactly what has happened. In more sophisticated examples, the clients are sent information about the change in the object which may make it unnecessary for the client to request information from the object (either the clients get all the information they need or can use the information to determine that they’re not interested in the change). This is the way that, for instance, the .NET events system works, passing additional information in the e/EventArgs parameter. Other variations allow the clients to specify what information they’re interested in receiving and avoid being notified about all changes in the object. The Observer pattern (and many others) are described in Learning Tree’s 511 course, .NET Best Practices and Design Patterns.

Peter Vogel

Talking to SignalR Hubs from .NET Clients (and fixing version incompatibilities)

In an earlier post I showed how to set up a SignalR hub that would accept requests and send out messages to browser-based, JavaScript clients.  What’s special about SignalR is that those messages are immediately picked up by the browser-based clients like the one I created in the following post (at least, the messages are received immediately with more modern browsers–with older browsers, SignalR falls back on having the browser regularly check for updated information).

However, so far I’ve assumed that the information to go to the server was generated in JavaScript from one of  those browser-based clients. I suspect that, in most cases, the information that clients are interested in–updates and changes to data–is generated at the server, rather than at the client. For instance, it will be updates to server-side data made by one of the other clients that will be of interest to all the rest of the clients (e.g. “Last ticket sold!”, “Customer X has been updated!”). Those updates will be made by server-side code either in a page being posted back to the server or in a server-side Web Service called from client-side JavaScript code. It’s also possible that the client making these updates may not be one of the clients receiving messages from the hub…or may not even be part of the application at all: it may be some external application  making the update (or be an application that monitors the data for updates in order to notify the hub of changes). In these scenarios, it will be .NET, not JavaScript, code that will need to send the information to the hub to be distributed to the clients accepting messages from the hub.

And that’s what this post is all about: integrating non-.NET clients into a SignalR hub. And, along the way, I’ll discuss how to handle having incompatible versions of SignalR on the server and the client (hey: as I said in my first post, this is pre-release software–these kind of problems are going to happen).

Talking to the Hub From Inside the Application

If the data that clients are interested in is being generated by server-side code inside the application with the hub, your server-side code can just piggyback on the hub. The first step in that process is to retrieve a reference to the hub using the GetHubContext method  through the ConnectionManager property of SignalR’s GlobalHost class (the property is static/shared so you don’t need to instantiate the class). You need to specify the type of the hub class that will be returned from the method. My hub was a class called MessageHub, so server-side code in that application to work with that hub would look like this:

Dim hub As IHubContext
hub = GlobalHost.ConnectionManager.GetHubContext(Of MessageHub)()

Now that you have a reference to the hub, you can all the methods set up on the client as you did from inside the hub’s methods. This code, for instance, sends a message to any client that’s implemented AcceptMessage:

hub.Clients.All.AcceptMessage("from server")

One warning: If you’ve try testing this with the WebForm you’ve been using as your client for accepting messages from your hub, don’t be surprised if your message doesn’t get back to the client. During the time your page is posting back to the server and executing this code, the page isn’t present in the browser to receive the message. You’ll need two clients to test this effectively (in IE just right-click on your page’s tab and select Duplicate Tab to create a second client to receive messages while the first client is posting back to the server).

Talking to the Hub From Other Applications

You can also send messages to your hub from .NET applications. The first step is to use NuGet to add the client-side libraries (Microsoft.AspNet.SignalR.Client) to your application. This can cause problems when you go to test your application: You may get the message “Incompatible protocol version” (or the proposed upgraded version of this message: “You are using a version of the client that isn’t compatible with the server. Client version a, server version b.”). The problem is that the version of the client library that you’re using isn’t compatible with the version of the library that your server is using–see the section at the end of this post for how to resolve this.

The first step in the code to have a non-JavaScript client connect to a hub is to instantiate a HubConnection object, passing the URL for the Website with your hub. This code, which I used in a WPF application, does that:

Imports Microsoft.AspNet.SignalR.Client.Hubs

Class MainWindow
  Private conn As HubConnection
  Private hub As IHubProxy

  Private Async Sub InitializeHub()
    conn = New HubConnection("http://localhost:49206/")

Once you’ve created the HubConnection, you create a HubProxy (or, to be more specific, a class that implements the IHubProxy interface) using the HubConnection object’s CreateHubProxy method and passing the name of the hub that you want to talk to as a string. This code connects to the class I called MessageHub that I created back in my first post:

hub = conn.CreateHubProxy("MessageHub")

As in the JavaScipt code, you must now start the connection by calling the Start method. The Start method is asynchronous and, in this code, I’ve chosen to wait until that method completes (which is why I’ve put this code in a separate method: I could add the Async keyword to the method to allow me to use the Await keyword):

  Await conn.Start
End Sub

Once the connection is open, you can send messages by using the HubProxy object’s Invoke method–just pass the name of your method on the server (in my case, “ReceiveMessage”) followed by whatever parameters the the method requires (in my case that’s a single string).  The Invoke method is asynchronous but, here, I’m not going to wait for it to finish:

hub.Invoke("ReceiveMessage", "Hello, World form a .NET Client!")

Since I’m using a WPF application rather than a Web browser I have some control over what happens when the user closes the application. The decent thing for me to do, as part of unloading my application, is to tell the hub that I’m done by calling the HubConnection object’s Stop method:

Private Sub MainWindow_Closing(sender As Object, e As ComponentModel.CancelEventArgs) Handles Me.Closing
  conn.Stop()
End Sub

For completeness sake: Your non-JavaScript clients can also receive messages from the server. When I set up my hub, I had it send messages through an AcceptMessage function on the client. In non-JavaScript clients, I can get the messages sent using AcceptMessage by using the HubProxy’s On method. I just need to specify the type of data I’ll be receiving (string, in my case), the name of the function that the hub is using (AcceptMessage), and provide a lambda expression that will be passed the message when the hub sends it. This code displays a message when the hub sends one out:

hub.On(Of String)("acceptMessage", Function(m) MessageBox.Show(m))

With these additions, you can now send information to your MessageHub that it can distribute to clients. In my next post, I’ll start a case study that will pull all of this proof-of-technology stuff together into something resembling a useful application.

This following section discusses handling those “incompatible protocol/versioning” problems I mentioned earlier and you can safely ignore it until you have the problem.

Dealing with Version Compatibilities

The protocol versioning problem I mentioned earlier can happen if the NuGet versions of your client- and server-side libraries aren’t coordinated at Microsoft’s end (it could happen!) or, more likely, if the libraries have been updated since you created your server and NuGet is delivering a newer version of the libraries to your client project. You have two solutions to the problem: update your server software to the latest version (i.e. use the NuGet manager to remove the current version of SignalR from your server and then use NuGet to add the latest version back in) or download an earlier version of the client software to your client to get a version compatible with your older server version.

If updating the server doesn’t work (or you’d prefer to not to “fix” your working server) rolling back your client to an earlier version isn’t hard. First, use the NuGet manager to remove your client’s existing package. Then go to the list of all the versions of the client software and click on the version you want. That will take you to that version’s download page. The PackageManager command you need to install this version is listed at the top of the page (something like Install-Package Microsoft.AspNet.SignalR.Client -Version 1.0.0-rc2 -Pre). Copy it. Now, to use the command, from the Tools menu, select Library Package Manager | Package Manager Console to display the console, which will (probably) appear in a window at the bottom of Visual Studio. Paste in the command, hit the <Enter> key, and you’ve rolled your client back to the earlier version.

Peter Vogel

Accepting and Sending Messages in JavaScript with SignalR

In my last post, I showed how to use Microsoft’s new SignalR technology to create a server-side “hub” that would accept messages from clients and forward that message on to all connected clients. What’s special about SignalR is that, with a modern browser, those connected clients don’t have to send a request to the server to get their messages–the browsers will, receive their messages as soon as the hub sends the message (and the message will still get through with less up-to-date browsers though they will automatically fall back to older polling based methods).

In that last post I set up a hub (I called it MessageHub) with a method (called ReceiveMessage) that clients could call to pass a text string to the server–if you’ve forgotten what that hub looked like, I’ve repeated it at the end of this column with one tweak. My ReceiveMessage method called a function on the clients (named acceptMessage) to send that text string out to all connected clients. In this post, I’m going to show how to set up a JavaScript client to receive that message. I’ll also show how to send a message from your server-side hub back to all of the clients except the client that sent the message (it doesn’t make much sense to me to send the message to its originator).

Accepting Messages in JavaScript

The first step in creating a Web page that will accept messages from a server-side hub is to add the script libraries that the page will need. The order of these libraries matters so add them as shown below (I’ve put my libraries in a Scripts folder in my application but you can keep them anywhere you want in your project). While you must add a script tag for the last library (signalr/hubs) you won’t have that library in your project–it’s a proxy library that’s generated for your application by SignalR:

<script type="text/javascript" src="Scripts/jquery-1.6.4.min.js"></script>
<script type="text/javascript" src="Scripts/json2.min.js"></script>
<script type="text/javascript" src="Scripts/jquery.signalR-1.0.0-rc2.min.js"></script>
<script type="text/javascript" src="/signalr/hubs"></script>

Now you’re ready to use some JavaScript to open a connection to your hub. Presumably, you’ll want to do this when the page first starts so, in the following code, I use the jQuery ready function (“$(function() {…”) to hold the code to make the connection. SignalR is implemented as a jQuery add-in so you use the jQuery identifier ($) to call the SignalR function called connection. You must also specify which of your application’s server-side hubs you’ll be connecting with by tacking on the name of your hub class to the connection function (the first letter of your hub class must be lowercased). So, to open a connection to my MessageHub class, I would use code like this:

<script type="text/javascript">
var conn;
$(function () 
  {
   conn = $.connection.messageHub;

The next step is to provide a function for the hub to call when the hub has a message to send to your client. When you created the hub, you specified the name of that function (I used AcceptMessage) and the number of parameters that would be passed (I used one parameter).  In the browser page, you add a property with the function name to the connection’s client property. Once that property is added, just set the property to the function you want to execute when the hub sends out a message using that function name.

This code defines a function with a single parameter (to match what my server-side code calls) and inserts the function into a property called AcceptMessage (to match the name I used in my server-side code–casing doesn’t seem to matter here). The function finds an element on the page with its id attribute set to messages and appends the text in the parameter passed from the server to that element:

 conn.client.AcceptMessage = function (message) 
  {
    $('#messages').append('message');
  };

However, before the hub can send messages to your page (or you can send messages to the hub) you must start the connection by calling the start function on the hub property of the SignalR connection. This is an asynchronous process so you can’t be sure when it will complete–I’ll come back to that issue.

Sending Messages in JavaScript

You can also send messages to the server from JavaScript. In an ASP.NET application, I’d probably wire up a JavaScript function for sending messages to a Button object, using the Button’s OnClientClick property:

<asp:Button ID="sendMessageBtn" runat="server" Text="Connect" OnClientClick="return SendMessage();"/>

Again, to keep everything as simple as possible, all I’m going to do in my SendMessage function is call the method I created in my server-side hub (which I called ReceiveMessage). That method accepted a single parameter, a text string. To call your server-side method, you use the server property on the connection object, followed by the name of the method in your hub (again, with the first letter of the method name in lowercase). Calling my server-side RecieveMessage method and passing a single string parameter looks like this:

function SendMessage()
{
  conn.server.receiveMessage("Hello, World!");
  return false;
}

Before you can either accept or send messages, however, you must start the connection by calling it’s start function–which is an asynchronous operation. If  you’d prefer to wait until the start function successfully connects to the server-side hub before wiring up your Button’s click event you can use the done function on the start method to wait for the start method to complete.

This code not only starts the connection but also wires up my SendMessage function to the Button with its id attribute method set to sendMessageBtn when the start method completes:

$.connection.hub.start().done($('#sendMessageBtn').click(SendMessage));

With this change, I don’t need to use the OnClientClick property on my Button:

<asp:Button ID="sendMessageBtn" runat="server" Text="Connect"/>

Ignoring the Sender

To finish up this example: When returning the message, it doesn’t make much sense for the hub to send the message back to the client that originated it. In my server-side hub, I originally used this code to call a function called AcceptMessage on all the connected clients:

Me.Clients.All.AcceptMessage(Message)

However, I can use the AllExcept method to send messages to all clients except for those I specify in an array. I can specify a particular client by using that client’s ConnectionId. Fortunately, I can retrieve the ConnectionId of the client I’m currently processing from my hub’s Context property. So, to send a message back to all of my clients except the one who sent the message, I would rewrite my hub to look like this:

Imports System
Imports System.Web
Imports Microsoft.AspNet.SignalR

Public Class MessageHub
           Inherits Hub

  Public Sub ReceiveMessageOther(Message As String)
    Me.Clients.AllExcept(Me.Context.ConnectionId).AcceptMessage(Message)
  End Sub

End Class

However, SignalR provides a shortcut for doing this–just use the Others property on Clients to send a message to all the connected clients other than the calling client:

Me.Clients.Others.AcceptMessage(Message)

Of course, what I’ve created so far is just barely an application where the server calls the client when the server “knows” something that the client would like to know. Right now, only other JavaScript clients can add to the server’s store of information. In my next post, I’ll set up some  non-JavaScript clients (from both inside and outside the application) to provide information to the server that it can pass on to its JavaScript clients (and also have those non-JavaScript clients accept messages from the hub).

Peter Vogel

Having the Server Call the Client with SignalR

Microsoft’s latest technology for creating Web Services–SignalR–addresses an interesting problem in creating modern applications: two-way communication. The whole point of Web Services is that the server “knows” something that the client does not. To get that information the client calls the service to get that information. However, in a volatile environment (where data on the server frequently changes) with a long running client (where the client stays connected to the server while that volatile data changes) and critical information (the client wants to stay up-to-date with the server’s changes) it may be necessary for the client to be updated as data changes on the server. With the original design of Web Services that was only possible through “long polling”: the client keeps calling the service to ask “Has anything changed?” That’s terrifically inefficient in two ways: Either the client waits a long time between checking so that, when the client does get the information, the data is stale and/or out-of-date; The client checks frequently so that the server is battered with requests when, most time, nothing has changed. The right answer is to have the server call the client when something changes. The trick is to find an interoperable, industry standard way to do that.

There are a couple of HTML5 solutions to this problem that stay interoperable: using server-side events or WebSockets, for instance. But the problem with HTML5 is that not all modern browsers support all of the various HTML5 specs…and, anyway, not all users are using modern browsers. SignalR provides a single interface for letting the server call the client and does that by concealing from the developer how this magic is achieved: SignalR will use WebSockets if the browser supports it but (in the absence of WebSockets) will revert to other technologies, including long polling if necessary.

And, before I go any further, I should point out that SignalR is still only in “release candidate” mode. It’s possible that Microsoft might never release a final version of this technology (as happened with Upshot) or, better yet, might roll this into some other technology (the ASP.NET Web API would be my choice, as covered in Learning Tree’s 2601 course, Introduction to WCF and Web API Services).

Accepting and Sending Messages at the Server

A simple SignalR application consists of a server-side hub that can receive requests from clients (JavaScript or otherwise) and send messages to those clients. On the server you just need to register that you’re using SignalR and the SignalR server-side component will route all incoming SignalR requests to methods on “hubs” that you define. Similarly, any messages generated by your hubs will be sent out to clients that have connected to the hub. In the browser, you need to establish a connection to a server-side hub, calls methods on the hubs you’re connected to, and define client-side functions for the server-side hub to use when sending out messages.  This post will start to demonstrate  how to create a simple broadcast application: all messages sent from any browser-based client are sent to all other browser-based clients. In the following posts, I’ll build on this to show how to accept messages from non-JavaScript clients and how to handle communication with individual clients. I’ll do all of this in an ASP.NET WebForms project but nothing important would change in, for instance, an ASP.NET MVC project.

The first step is to use NuGet to add the SignalR package to your project. Since this is pre-release software you’ll need, in the NuGet Manager dialog, to  set the top-left dropdown list to “Include Prerelease.” After adding the “Microsoft ASP.NET SignalR” package, you’ll also need to add the JSON2 package. Since SignalR is implemented as a jQuery add-in you’ll need ensure that you have some version of the jQuery library in your project.

Your next step is to add a server-side SignalR hub to process requests from clients. A hub is a class that inherits from Microsoft.AspNet.SignalR.Hub–do not put this class in the App_Code folder of an ASP.NET project (the client can’t find a class in the App_Code folder). In your hub you need, at the very least, a method that clients can call in order to pass data to the hub. For this case study, I’ll use a method that accepts a single parameter from the client–a text string–and sends that text string to all connected clients. In real life, of course, the method would presumably do some processing on the incoming message and might select which clients are to get the message–tune into later posts for how to do that. Later posts will also use more complex objects than a text string. In this server-side method,  you’ll use SignalR’s HubConnectionContext object which you can retrieve fro the Clients property of you hub class. The HubConnectionContext object’s All property lets you work with all the connected Clients to call a JavaScript function (in browsers) or a lambda expression (in .NET applications) on the clients.

The following code defines a method (which I’ve called ReceiveMessage) in a hub (called MessageHub) that clients can call to send a message to all other clients. The method then calls a function (called acceptMessage) on all the all connected clients (since this method name is one you define, you won’t get any IntelliSense support when you type the function name in):

Imports System
Imports System.Web
Imports Microsoft.AspNet.SignalR

Public Class MessageHub
    Inherits Hub

    Public Sub ReceiveMessage(Message As String)
        Me.Clients.All.acceptMessage(Message)
    End Sub

End Class

To get messages routed to the hubs in your application, you need to register your hubs with SignalR. That requires a single line in your Application_Start method in your Global.asax file (for ASP.NET) or wherever you define your routing rules (in ASP.NET MVC). You’ll need to add an imports statement for System.Web.Routing to make this code work:

Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
        RouteTable.Routes.MapHubs()
End Sub

My next post will look at what’s required in a JavaScript client to accept this message (and how to avoid sending the message to all clients).

Peter Vogel


Learning Tree International

.NET & Visual Studio Courses

Learning Tree offers over 210 IT training and Management courses, including a full curriculum of .NET training courses.

Free White Papers

Questions on current IT or Management topics? Access our Complete Online Resource Library of over 65 White Papers, Articles and Podcasts

Enter your email address to subscribe to this blog and receive notifications of new posts by e-mail.

Join 29 other followers

Follow Learning Tree on Twitter

Archives

Do you need a customized .NET training solution delivered at your facility?

Last year Learning Tree held nearly 2,500 on-site training events worldwide. To find out more about hosting one at your location, click here for a free consultation.
Live, online training

%d bloggers like this: