Introduction
Well, let us start at the beginning and firstly discuss what SignalR is.
SignalR is a newish Microsoft technology that enables us to build real-time applications, where clients can push data to the server, and the server can push data to all clients.
It works with the new HTML5 WebSockets API that enables bi-directional communication between clients (desktop applications, as well as browsers) and server. If WebSockets are not available, it gracefully falls back onto other technologies, without any changes in code. It also builds on OWIN (Open Web Interface for .NET).
This makes it very useful to build real-time applications, such as chat applications, monitor dashboards, etc.
The aim of this blog post is show how we can achieve this real-time communication between a server, and a desktop application. For the people starting to feel anxious, rest assured, this is not as complicated as it might sound. If you follow the steps below, you will see it isn't such a daunting task at all.
Let us break the explanation down to the following steps:
- Create the SignalR hub for the server
- Create desktop application that connects to the SignalR hub
- Send message from the client application to the server
- Send message from the server to the client
Using the Code
Create the SignalR Hub
One of the most important things to understand when implementing SignalR is that at the center of it all, is what we call a "Hub". This hub is what enables communication between the server and clients.
Before we create a sample hub, we first need to decide how we want to host the hub. There are various options when it comes to hosting a SignalR hub, all with their own advantages and disadvantages.
Some of the hub-hosting options available to us are:
- Self-hosting
- IIS-hosting
- Windows service-hosting
The service-hosting options for example is a good choice if you need the hub to always be on, and it can for example be restarted automatically when the machine restarts.
To keep things simple for this post, I am going to make use of the self-hosting option, and we are going to host the SignalR hub inside a simple console application.
So let's get started:
- Open Visual Studio, and create a new Console application
- We will need to install some Nuget packages onto this application. You can do this through the GUI, or by running the following commands in the Package Manager Console:
Install-Package Microsoft.AspNet.SignalR.SelfHost
Install-Package Microsoft.Owin.Cors
Next let us create the hub itself:
- Create a new
public
class and call it something like TestHub
- Let
TestHub
inherit from Hub
- You can optionally give the
Hub
a new name by slapping a HubName
attribute on the class, like so:
[HubName("TestHub")]
At the moment, the hub has no functionality yet, but let us start by seeing how easy it is to start up the hub when the console application is started.
Create a new class called Startup
, or whatever you like and add the following code to it:
public void Configuration(IAppBuilder app)
{
app.UseCors(CorsOptions.AllowAll);
app.MapSignalR();
}
This simply enables the hub to communicate cross-domain, and correctly maps all the SignalR hubs in the application for us.
Next step is to add the call in the application's entry point to create a new hub for us and this can easily be done with the following code (note Startup
in the following code refers to the class we just created):
static void Main(string[] args)
{
string url = @"http://localhost:8080/";
using (WebApp.Start<startup>(url))
{
Console.WriteLine(string.Format("Server running at {0}", url));
Console.ReadLine();
}
}
That is all we need to do to create a SignalR hub.
You can test that everything is working as expected by running the application and browsing to the following URL in your browser. If it is working, you will see a bunch of SignalR related code.
http://localhost:8080/signalR/hubs
So far, so good? Easy, right? :)
Let us now move on to the desktop application.
Creating the Desktop Client
For this post, I am going to be using another console application, but you can use Winforms, WPF, or whatever your heart desires, keeping in mind that this tutorial focuses on getting desktop applications to work with SignalR. Web applications also work great with SignalR, but will not be covered in this post.
First, we will need to install the SignalR client Nuget package onto the client project. As with the Hub
, this can be done either via the GUI, or the Package Manager Console. The commands for the console are given below:
Install-Package Microsoft.AspNet.SignalR.Client
Once this is done, we need to create a proxy to the HubConnection
. This can easily be done with a couple of lines of code:
static void Main(string[] args)
{
IHubProxy _hub;
string url = @"http://localhost:8080/";
var connection = new HubConnection(url);
_hub = connection.CreateHubProxy("TestHub");
connection.Start().Wait();
}
That is all there is to it to connect to a SignalR hub.
Note at this stage the application will close after the connection is made, because it has nothing keeping it running. We will improve on this in the next step.
Next, we will tackle the actual communication between the server and client.
Send Message from the Client
Caveat
The most important thing to understand when setting up communication between the server and client is that most of SignalR makes use of dynamic
objects, so spelling is very important. Fear not non-grammar Nazis. I am not talking spelling as in the words are spelt correctly, according to some dictionary, only that the same spelling of method names are used on the server and client. The reason for this will soon become clear.
To keep things simple for this post, let's create a method on the server that will receive some string
value, and return the length of the string
in the client.
I'll admit, this is not the most exciting thing on earth to do with a realtime application, but humour me.
To start, in the Client, we need to add code that will invoke a specific method on the Hub
, and this is where spelling becomes important. So in the client, add the following after the part where the SignalR connection is opened:
string line = null;
while ((line = System.Console.ReadLine()) != null)
{
_hub.Invoke("DetermineLength", line).Wait();
}
Note the DetermineLength
portion in the section above. SignalR will attempt to call a method on the TestHub
with that exact same name and parameters, in this case a string
value.
So let us now create the corresponding method, that will receive this sent data, on TestHub
by adding the following code:
public void DetermineLength(string message)
{
Console.WriteLine(message);
}
Note that even though we want to return something, this method has a void
return type.
We can now run the solution and ensure that the message arrives at the TestHub
as expected by verifying that it gets printed to the console on the server.
If you can't see anything being printed in the console, verify that the method names are spelled exactly the same.
After we have verified that our messages are being received and processed by the hub, we can focus on communicating back to the client application.
Send Message from the Server
There are various ways to communicate back with clients connected to the hub. We can respond only to the calling client, send data to all connected clients, or even just a select few. We might delve into this in a future post. For now however, we are going to respond to all connected clients.
So let us concatenate the length of the string to the received message and respond back to the client(s). Add the following lines to your code:
public void DetermineLength(string message)
{
Console.WriteLine(message);
string newMessage = string.Format(@"{0} has a length of: {1}", message, message.Length);
Clients.All.ReceiveLength(newMessage);
}
Note the ReceiveLength
in the code above. SignalR will attempt to call a method on the client with that exact same name and parameter.
So let's go back to our client application and add the code that will receive this data, and do something with it.
In our client application, add the following code:
_hub.On("ReceiveLength", x => Console.WriteLine(x));
The On
method specifies a method name and an action. So whenever the SignalR hub sends a message to the method, that specific action will get executed. In our example, it will just print out the message with its length to the console.
And there, we have it! Bidirectional communication using SignalR. Gold star for you!
We can now even have multiple client applications running and each one will respond to other's input as well. Go ahead, try it. You know you want to...
Conclusion
In this post, we have seen how simple it is to create a realtime application with SignalR. It is a very powerful technology, and we have just scraped the surface, but hopefully this article is enough to get you interested and excited about the SignalR and its potential uses.