7 min read

(For more resources related to this topic, see here.)

Moving up one level

While PersistentConnection seems very easy to work with, it is the lowest level in SignalR. It does provide the perfect abstraction for keeping a connection open between a client and a server, but that’s just about all it does provide. Working with different operations is not far from how you would deal with things in a regular socket connection, where you basically have to parse whatever is coming from a client and figure out what operation is being asked to be performed based on the input. SignalR provides a higher level of abstraction that removes this need and you can write your server-side code in a more intuitive manner. In SignalR, this higher level of abstraction is called a Hub. Basically, a Hub represents an abstraction that allows you to write classes with methods that take different parameters, as you would with any API in your application, and then makes it completely transparent on the client—at least for JavaScript. This resembles a concept called Remote Procedure Call (RPC), with many incarnations of it out there.

For our chat application at this stage, we basically just want to be able to send a message from a client to the server and have it send the message to all of the other clients connected. To do this, we will now move away from the PersistentConnection and introduce a new class called Hub using the following steps:

  1. First, start off by deleting the ChatConnection class from your Web project.

  2. Now we want to add a Hub implementation instead. Right-click on the SignalRChat project and select Add | New Item.

  3. In the dialog, chose Class and give it a name Chat.cs.

  4. This is the class that will represent our Hub. Make it inherit from Hub:

    Public class Chat : Hub

  5. Add the necessary import statement at the top of the file:

    using Microsoft.AspNet.SignalR.Hubs;

  6. In the class we will add a simple method that the clients will call to send a message. We call the method Send and take one parameter into it; a string which contains the message being sent by the client:

    Public void Send(string message)
    {
    }

  7. From the base class of Hub, we get a few things that we can use. For now we’ll be using the Clients property to broadcast to all other clients connected to the Hub. On the Clients property, you’ll find an All property which is dynamic; on this we can call anything and the client will just have to subscribe to the method we call, if the client is interested.

    It is possible to change the name of the Hub to not be the same as the class name. An attribute called HubName() can be placed in front of the class to give it a new name. The attribute takes one parameter; the name you want for your Hub. Similarly, for methods inside your Hub, you can use an attribute called HubMethodName() to give the method a different name.

  8. The next thing we need to do is to go into the Global.asax.cs file, and make some changes. Firstly, we remove the .MapConnection(…) line and replace it with a .MapHubs() line. This will make all Hubs in your application automatically accessible from a default URL. All Hubs in the application will be mapped to /signalr/<name of hub>; so more concretely the path will be: http:// <your-site>:port/signalr/<name of hub>. We’re going with the defaults for now. It should cover the needs on the server-side code.

  9. Moving into the JavaScript/HTML part of things, SignalR comes with a JavaScript proxy generator that can generate JavaScript proxies from your Hubs mapped using .MapHubs(). This is also subject to the same default URL but will follow the configuration given to .MapHubs().We will need to include a script reference in the HTML code right after the line that references the SignalR JavaScript file. We add the following:

    <script src = "/signalr/hubs" type="text/javascript"></script>

    This will include the generated proxies for our JavaScript client. What this means is that we get whatever is exposed on a Hub generated for us and we can start using it straight away.

  10. Before we get started with the concrete implementation for our web client, we can move all of the custom code revitalizing the Rich Client, for PersistentConnection altogether.

  11. We then want to get to our proxy, and work with it. It sits on the connection object that SignalR adds to jQuery. So, for us, that means an object called chat will be there.

  12. On the the chat object, sit two important properties, one representing the client functions that get invoked when the server “calls” something on the client. And the second one is the property representing the server and all of the functionalities that we can call from the client. Let’s start by hooking up the client and its methods. Earlier we implemented in the Hub sitting on the server a call to addMessage() with the message. This can be added to the client property inside the chat Hub instance:

  13. Basically, whenever the server calls that method, our client counterpart will be called. Now what we need to do is to start the Hub and print out when we are connected to the chat window:

    $.connection.hub.start().done(function() {
    $("#chatWindow").val("Connectedn");
    });

  14. Then we need to hook up the click event on the button and call the server to send messages. Again, we use the server property sitting on the chat hub instance in the client, which corresponds to a method on the Hub:

    $("#sendButton").click(function() {
    chat.server.send($("#messageTextBox").val());
    $("#messageTextBox").val("");
    });

  15. You should now have something that looks as follows:

    You may have noticed that the send function on the client is in camelCase and the server-side C# code has it in PascalCase. SignalR automatically translates between the two case types. In general, camelCase is the preferred and the most broadly used casing style in JavaScript—while Pascal being the most used in C#.

  16. You should now be having a full sample in HTML/JavaScript that looks like the following screenshot:

  17. Running it should produce the same result as before, with the exception of the .NET terminal client, which also needs alterations. In fact, let’s just get rid of the code inside Program.cs and start over. The client API is a bit rougher in C#; this comes from the more statically typed nature of C#. Sure, it is possible—technically—to get pretty close to what has been done in JavaScript, but it hasn’t been a focal point for the SignalR team.

  18. Basically, we need a different connection than the PersistentConnection class. We’ll be needing a HubConnection class. From the HubConnection class we can create a proxy for the chat Hub:

  19. As with JavaScript, we can hook up client-side methods that get invoked when the server calls any client. Although as mentioned, not as elegantly as in JavaScript. On the chat Hub instance, we get a method called On(), which can be used to specify a client-side method corresponding to the client call from the server. So we set addMessage to point to a method which, in our case, is for now just an inline lambda expression.

  20. Now we need, as with PersistentConnection, to start the connection and wait until it’s connected:

    hubConnection.Start().Wait();

  21. Now we can get user input and send it off to the server. Again, as with client methods called from the server, we have a slightly different approach than with JavaScript; we call the Invoke method giving it the name of the method to call on the server and any arguments. The Invoke() method does take a parameter, so you can specify any number of arguments which will then be sent to the server:

  22. The finished result should look something like the following screenshot, and now work in full correspondence with the JavaScript chat:

Summary

Exposing our functionality through Hubs makes it easier to consume on the client, at least on JavaScript based clients, due to the proxy generation. It basically brings it to the client as if it was on the client. With the Hub you also get the ability to call the client from the server in a more natural manner. One of the things often important for applications is the ability to ?lter out messages so you only get messages relevant for your context.

Resources for Article :


Further resources on this subject:


LEAVE A REPLY

Please enter your comment!
Please enter your name here