Using a Persistent Connection

Exclusive offer: get 50% off this eBook here
SignalR Real-time Application Cookbook

SignalR Real-time Application Cookbook — Save 50%

Use SignalR to create real-time, bidirectional, and asynchronous applications based on standard web technologies with this book and ebook

$29.99    $15.00
by Roberto Vespa | April 2014 | Cookbooks Open Source Web Development

In this article by Roberto Vespa, the author of SignalR Real-time Application Development Cookbook, we will cover the following recipes:

  • Adding and registering a persistent connection

  • Sending messages from the server

  • Sending messages to the server

  • Exchanging messages between a server and a JavaScript client

  • Exchanging messages between a server and a .NET client

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

In our journey through all the features exposed by SignalR, so far we have been analyzing and dissecting how we can use the Hubs API to deliver real-time, bidirectional messaging inside our applications. The Hubs API offers a high-level abstraction over the underlying connection, effectively introducing a Remote Procedure Call (RPC) model on top it. SignalR is also offering a low-level API, which is the foundation Hubs is built on top of. However, it's also available to be used directly from inside our applications and it's called the Persistent Connection API.

A Persistent Connection API is a more basic representation of what the concrete network connection really is, and exposes a simpler and rawer API to interact with. We hook into this API by inheriting from a base class (PersistentConnection) in order to add our own custom Persistent Connection manager. It is the same approach we have been using when defining our custom Hubs by deriving from the Hub class. Through a registration step, we'll then let SignalR know about our custom type in order to expose it to our clients.

The PersistentConnection type exposes a few properties supplying entry points from where we send messages to the connected clients, and a set of overridable methods we can use to hook into the connection and messaging pipeline in order to handle the incoming traffic. This article will be an introduction to the Persistent Connection API, hence we'll be looking at just a portion of it in order to deliver some basic functionalities. We will also try to highlight what the peculiar attributes of this API are, which characterize it as a low-level one—still delivering powerful features, but without some of the nice mechanisms we have for free when using the Hubs API.

For the next four recipes, we will always start with empty web application projects, and we'll use simple HTML pages for the client portions. However, for the last one, we'll be building a console application.

Adding and registering a persistent connection

In this first recipe of the article, we'll introduce the PersistentConnection type, and we'll go into the details about how it works, how to use it, and how to register it into SignalR to expose it to the connected clients. Our goal for the sample code is to trace any attempt of connection from a client towards the exposed endpoint. We will also write a minimal JavaScript client in order to actually test its behavior.

Getting ready

Before writing the code of this recipe, we need to create a new empty web application that we'll call Recipe25.

How to do it...

Let's run through the steps necessary to accomplish our goal:

  1. We first need to add a new class derived from PersistentConnection. We can navigate to Add | New Item... in the context menu of the project from the Solution Explorer window, and from there look for the SignalR Persistent Connection Class (v2) template and use it to create our custom type, which we'll name EchoConnection. Visual Studio will create the related file for us, adding some plumbing code in it. For our recipe, we want to keep it simple and see how things work step by step, so we'll remove both methods added by the wizard and leave the code as follows:

    using Microsoft.AspNet.SignalR; namespace Recipe25 { public class EchoConnection : PersistentConnection { } }

    We could reach the same result manually, but in that case we would have to take care to add the necessary package references from NuGet first. The simplest way in this case would be to reference the Microsoft ASP.NET SignalR package, which will then bring down any other related and necessary module. The process of doing that has already been described earlier, and it should already be well known. With that reference in place, we could then add our class, starting with a simple empty file, with no need for any wizard.

  2. We then need to add an OWIN Startup class and set it up so that the Configuration() method calls app.MapSignalR<...>(...); in order to properly initiate the persistent connection class we just added. We should end up with a Startup.cs file that looks like the following code:

    using Microsoft.Owin; using Owin; [assembly: OwinStartup(typeof(Recipe25.Startup))] namespace Recipe25 { public class Startup { public void Configuration(IAppBuilder app) { app.MapSignalR<EchoConnection>("/echo"); } } }

    The usual Configuration() method calls MapSignalR(), but this time it uses a different overload, supplying EchoConnection as the type of our connection class and /echo as the name of the related endpoint. Behind the scenes, what MapSignalR() does is quite similar to what was happening when we were using the Hubs API; however, in this case, there is a little bit less magic because we have to explicitly specify both the type of the connection class and the URL from where it will be exposed. If we had more than one connection class to expose, we would have to call the MapSignalR() method once for each of them, and we would have to specify different URL addresses each time. It's worth noting that the endpoint name must begin with a / character. If we omit it, SignalR will raise an exception.

  3. Let's go back to our EchoConnection class and write some code to be executed when a new connection is performed. In order to achieve that, we have to override the OnConnected() method from PersistentConnection as shown in the following code:

    protected override Task OnConnected(IRequest request, string connectionId) { System.Diagnostics.Trace.WriteLine("Connected"); return null; }

    OnConnected() is one of the overridable methods mentioned in the Introduction section of the article, and its role is to give us a point from where we can handle every incoming connection.

    The first argument of the method is an instance of an object implementing the IRequest interface, which is a SignalR interface whose role is to describe the HTTP incoming request. It's similar to the very well-known ASP.NET Request object, but this version is much lighter and focused on what's needed in the context of SignalR, without exposing anything that could harm its efficiency, such as the (somewhat infamous) Session object or a read-write Cookies collection.

    The second argument is of type string and contains the connection identifier generated during the handshaking steps performed while setting up the connection.

    OnConnected() returns a Task instance, and in this way it's declaring its asynchronous nature. But, in our case, we do not really have anything special to send back to its caller, so finalizing the code of the method with return null; will be just fine.

    The only relevant line of code in our method is simply sending a diagnostic message to any Trace listener available.

    We are done, and it's been pretty straightforward. Now any client hitting the /echo endpoint will be handled by this class, and at every new connection, the OnConnect() method will be called. When we say new connection, we actually mean whenever SignalR performs a full handshaking cycle, selecting and applying a connection strategy. If a specific client (for example, a browser window) loses its connection and is able to reconnect just after the reconnection retry timeout has expired, a new full-blown connection will be built, a new connectionId value will be assigned to it and OnConnect() will be called again.

    We need a client to test if everything is working properly. To achieve this goal, let's add an HTML page called index.html, which we'll use to build our client. In this page, we'll link all the necessary JavaScript files that have already been added to the project when the Microsoft ASP.NET SignalR package has been referenced. Let's proceed.

  4. We first reference jQuery using the following code:

    <script src = "Scripts/jquery-2.1.0.js"></script>

  5. Then we need to link the SignalR JavaScript library with the following line of code:

    <script src = "Scripts/jquery.signalR-2.0.2.js"></script>

    At this point, we used to add a reference to the dynamic hubs endpoint in the previous recipes, but this is not the case here. We do not need it because we are not using the Hubs API, and therefore we don't need dynamic proxies that are typical of that way of using SignalR. The SignalR JavaScript library that we just added contains all that's necessary to use the Persistent Connection API.

  6. We finally add a simple script to connect to the server as follows:

    <script> $(function() { var c = $.connection('echo'); c.start() .done(function(x) { console.log(c); console.log(x); //x and c are the same! }); }); </script>

    Here we first interact with the $.connection member we already saw when describing the Hubs API, but in this case we do not use it to access the hubs property. Instead, we use it as a function to ask SignalR to create a connection object pointing at the endpoint we specify as its only argument (echo). The returned object has a similar role to the one the hubs member has; in fact, we can call start() on it to launch the actual connection process, and the returned value is again a JavaScript promise object whose completion we can wait for, thanks to the done() method, in order to ensure that a connection has been fully established. Our simple code prints out both the connection object we obtained (the c variable) and the argument supplied to the done() callback (the x variable) just to show that they are actually the same object, and we are free to pick any of them when a connection reference is needed.

To test what we did, we just need to run the project from Visual Studio and open the index.html page using the Developer Tools of the browser of choice to check the messages printed on the browser console.

How it works...

The SignalR $.connection object exposes the low-level connection object, which is the real subject of this article. Its server-side counterpart can be any type derived from PersistentConnection that has been previously registered under the same endpoint address targeted when calling the $.connection() function. Any major event happening on the connection is then exposed on the server by events that can be intercepted by overriding a bunch of protected methods. In this recipe, we saw how we can be notified about new connections just by overriding the OnConnected() method. We'll see a few more of those in future recipes.

The rest of the client-side code is very simple, and it's very similar to what we have been doing when starting connections with the Hubs API; the only big difference so far is the fact that we do not use the dynamically generated hubs member anymore.

Sending messages from the server

Now that we have a good idea about how PersistentConnection can be registered and then used in our applications, let's go deeper and start sending some data with it. As usual, in SignalR, we need a client and a server to establish a connection, and both parts can send and receive data. Here we'll see how a server can push messages to any connected client, and we'll analyze what a message looks like.

We already mentioned the fact that any communication from client to server could, of course, be performed using plain old HTTP, but pushing information from a server to any connected client without any specific client request for that data is not normally possible, and that's where SignalR really helps.

We'll also start appreciating the fact that this API stands at a lower level when compared to the Hubs API because its features are more basic, but at the same time we'll see that it's still a very useful, powerful, and easy-to-use API.

Getting ready

Before writing the code for this recipe, we need to create a new empty web application, which we'll call Recipe26.

How to do it...

The following are the steps to build the server part:

  1. We first need to add a new class derived from PersistentConnection, which we'll name EchoConnection. We can go back to the previous recipe to see the options we have to accomplish that, always paying attention to every detail in order to have the right package references in place. We want to end up with an EchoConnection.cs file containing an empty class having the following code:

    using Microsoft.AspNet.SignalR; namespace Recipe26 { public class EchoConnection : PersistentConnection { } }

  2. We then need to add the usual OWIN Startup class and set it up so that the Configuration() method calls app.MapSignalR<EchoConnection> in order to properly wire the persistent connection class we just added ("/echo"); to our project. This is actually the same step we took in the previous recipe, and we will be doing the same through the remainder of this article. The final code will look like the following:

    using Microsoft.Owin; using Owin; [assembly: OwinStartup(typeof(Recipe26.Startup))] namespace Recipe26 { public class Startup { public void Configuration(IAppBuilder app) { app.MapSignalR<EchoConnection>("/echo"); } } }

  3. Back to our EchoConnection class, we want to redefine the OnConnected() overridable method, whose function we already described earlier, and from there send a message to the client that just connected. This is as simple as coding the following:

    protected override Task OnConnected(IRequest request, string connectionId) { return Connection.Send(connectionId, "Welcome!"); }

    The PersistentConnection class exposes several useful members, and one of the most important is for sure the Connection property, of type IConnection, which returns an object that allows us to communicate with the connected clients. A bunch of methods on the IConnection interface let us send data to specific sets of connections (Send()), or target all the connected clients at the same time (Broadcast()). In our example, we use the simplest overload of Send() to push a string payload down to the client that just connected. Both Send() and Broadcast() run asynchronously and return a Task instance, which we can directly use as the return value of the OnConnect() method.

    Another relevant member inherited from PersistentConnection is the Groups member, which exposes a couple of Send() overloads to push messages down to connections belonging to a specific group. Groups also exposes a set of capabilities to manage the members of specific groups the same way the Hubs API does. There is no conceptual difference here with what we explained earlier, therefore we'll skip any further explanation about it.

    All the methods we just mentioned expect a last parameter of type object, which is the actual payload of the call. This value is automatically serialized before going on the wire to reach the clients. When there, the involved client library will deserialize it, giving it back its original shape using the best data type available according to the actual client library used (JavaScript or .NET). In our example, we used a simple string type, but any serializable type would do, even an anonymous type.

    Back to this sample, any client connecting to the /echo endpoint will be handled by the OnConnect() method exposed by EchoConnection, whose body will send back the message Welcome! using the Send() call.

Let's build an HTML page called index.html to host our client code. In this page, we'll link all the necessary JavaScript files as we already did in the previous recipe, and then we'll add a few lines of code to enable the client to receive and log whatever the server sends.

  1. We first reference jQuery and SignalR with the following code:

    <script src = "Scripts/jquery-2.1.0.js"></script> <script src = "Scripts/jquery.signalR-2.0.2.js"></script>

  2. We then add the following simple piece of script:

    <script> $(function () { var c = $.connection('echo'); c.received(function(message) { console.log(message); }) .start(); }); </script>

    Here, we first interact with the $.connection member in the same way we did in the previous recipe, in order to create a connection object towards the endpoint we specify as its argument (echo). We can then call start() on the returned object to perform the actual connection, and again the returned value is a JavaScript promise object whose completion we could wait for in order to ensure that a connection has been fully established. Before starting up the connection, we use the received() method to set up a callback that SignalR will trigger whenever a message will be pushed from the type derived from PersistentConnection down to this client, regardless of the actual method used on the server side (Send() or Broadcast()). Our sample code will just log the received string onto the console. We'll dig more into the received() method later in this article.

We can test our code by running the project from Visual Studio and opening the index.html page using the Developer Tools of the browser to see the received message printed onto the console.

How it works...

Any type derived from PersistentConnection that has been correctly registered behind an endpoint can be used to send and receive messages. The underlying established connection is used to move bits back and forth, leveraging a low-level and highly optimized application protocol used by SignalR to correctly represent every call, regardless of the underlying networking protocol. As usual, everything happens in an asynchronous manner.

We have been mentioning the fact that this is a low-level API compared to Hubs; the reason is that we don't have a concept of methods that we can call on both sides. In fact, what we are allowed to exchange are just data structures; we can do that using a pair of general-purpose methods to send and receive them. We are missing a higher abstraction that will allow us to give more semantic meaning to what we exchange, and we have to add that ourselves in order to coordinate any complex custom workflow we want to implement across the involved parts. Nevertheless, this is the only big difference between the two APIs, and almost every other characteristic or capability is exposed by both of them, apart from a couple of shortcomings when dealing with serialization, which we'll illustrate later in this article.

You might think that there is no real need to use the Persistent Connection API because Hubs is more powerful and expressive, but that's not always true. For example, you might imagine a scenario where you want your clients to be in charge of dynamically deciding which Hubs to load among a set of available ones, and for that they might need to contact the server anyway to get some relevant information. Hubs are loaded all at once when calling start(), so you would not be able to use a Hub to do the first handshaking. But a persistent connection would be just perfect for the job, because that can be made available and used before starting any hub.

SignalR Real-time Application Cookbook Use SignalR to create real-time, bidirectional, and asynchronous applications based on standard web technologies with this book and ebook
Published: April 2014
eBook Price: $29.99
Book Price: $49.99
See more
Select your format and quantity:

Sending messages to the server

After looking at how to send messages from the server to the connected clients, let's swap sides and check how to perform the same operation, but in the opposite direction. We'll illustrate this scenario by building a simple JavaScript client that will send a message to the server as soon as the connection will be available.

This specific case is not really useful if taken alone, because any communication from client to server could be easily done by using plain old HTTP. However, when combined with the reception counterpart, it enables the construction of complex, real-time client-server workflows.

Getting ready

Before writing the code of this recipe, we need to create a new empty web application, which we'll call Recipe27.

How to do it...

Let's first check how to build the server portion using the following steps:

  1. We first add a new class named EchoConnection that is derived from PersistentConnection, as we already did in the previous recipes of this article, and we will clean up the content generated by Visual Studio in order to have an empty class body, as follows:

    using Microsoft.AspNet.SignalR; namespace Recipe27 { public class EchoConnection : PersistentConnection { } }

  2. As usual, we then add the OWIN Startup class with a Configuration() method calling app.MapSignalR<EchoConnection>("/echo"); to map our Remove class derived from PersistentConnection, as shown in the following code:

    using Microsoft.Owin; using Owin; [assembly: OwinStartup(typeof(Recipe27.Startup))] namespace Recipe27 { public class Startup { public void Configuration(IAppBuilder app) { app.MapSignalR<EchoConnection>("/echo"); } } }

  3. In our EchoConnection class, we can handle any incoming message in one place by simply overriding the OnReceived() method exposed by PersistentConnection as follows:

    protected override Task OnReceived(IRequest request, string connectionId, string data) { ... }

    This method will be called every time a client will use the available API method to send messages, and it will be supplied the following:

    • An instance of IRequest that contains some context information related to the current HTTP request

    • The identifier of the calling connection

    • A string payload containing the body of the request

    It's very basic and straightforward, but simple to use. One important detail we can appreciate here is the fact that the data payload is of type string, while the counterpart server-side Send() method we saw in the previous recipe was accepting any object and taking care of its serialization on the wire. In the case of OnReceived(), we stay at a lower level because the API does not offer any way to specify how the payload should be deserialized; therefore, the most sensible representation for the message is a string, which is the simplest way to represent the most common case of simple textual messages. This does not prevent us from sending more complex objects on the wire, but the deserialization task is not automatic, and we have to take care of it by ourselves.

  4. Let's complete the body of our OnReceived() method with a simple call to send what we just received to any Trace listener available, and then by returning a null value, as follows:

    System.Diagnostics.Trace.WriteLine( string.Format("Received: {0}", data)); return null;

Let's now build a corresponding client. As we always did through this article so far, we will use an HTML page called index.html. As usual, we'll need to reference the JavaScript files we already used in the previous recipes first, and then we'll add a couple of lines of code to send a message to the server as soon as the connection will be available.

  1. We first reference jQuery and SignalR using the following code:

    <script src = "Scripts/jquery-2.1.0.js"></script> <script src = "Scripts/jquery.signalR-2.0.2.js"></script>

  2. We then add our piece of script as follows:

    <script> $(function () { var c = $.connection('echo'); c.start() .done(function() { c.send('hello'); }); }); </script>

How it works...

Through the $.connection member, we first create a connection object pointing to the /echo endpoint, then we can call start() on it to perform the actual connection, and eventually we use the done() method to declare the function callback to be asynchronously invoked when the connection will be ready. Inside the callback, we can safely call the send() method on the connection object, passing on whatever value we want (in this case, a hello string). SignalR will take care of building a proper representation of it, serializing it as a string, and using JSON if necessary. As we already said earlier, the payload will be received by the server as a plain string anyway, so this feature is clearly handy on the client side but has to be handled with care because it forces us to perform an explicit deserialization step on the server.

We are done. Let's open the index.html page and check the Output window in Visual Studio to see the hello string printed out.

Exchanging messages between a server and a JavaScript client

Let's move on and put things together in order to build a simple test application where both the server and client will be sending and receiving payloads. To make things more interesting, we'll stop using simple strings, and we'll be illustrating how to handle serialization and deserialization of complex objects. In order to do that inside our type derived from PersistentConnection, we'll be using the JSON.Net library from Newtonsoft, which has been chosen as the default JSON handling library by the ASP.NET team, and it's already referenced any time you add SignalR on your server-side projects.

Getting ready

Before writing the code of this recipe, we need to create a new empty web application, which we'll call Recipe28.

How to do it...

As usual, we start with the server-side portion of the application using the following steps:

  1. We add a new class named EchoConnection that is derived from PersistentConnection, cleaning up the content generated by Visual Studio in order to have an empty class body:

    using Microsoft.AspNet.SignalR; namespace Recipe28 { public class EchoConnection : PersistentConnection { } }

  2. Let's then add the OWIN Startup class with a Configuration() method calling app.MapSignalR<EchoConnection>( "/echo"); to map the class derived from PersistentConnection as follows:

    using Microsoft.Owin; using Owin; [assembly: OwinStartup(typeof(Recipe28.Startup))] namespace Recipe28 { public class Startup { public void Configuration(IAppBuilder app) { app.MapSignalR<EchoConnection>("/echo"); } } }

  3. Back to our EchoConnection class, we can handle any incoming message by overriding the OnReceived() method exposed by PersistentConnection. That's where we will handle any incoming payload, analyze them, and build the corresponding response messages. In this example, we'll be using the Broadcast() method to distribute them to all the connected clients, as shown in the following code:

    protected override Task OnReceived(IRequest request, string connectionId, string data) { var payload = Newtonsoft.Json.JsonConvert .DeserializeAnonymousType( data, new { body = "" }); var body = string.Format("You said: {0}",payload.body); return Connection.Broadcast(new { body = body }); }

    We first make use of the JsonConvert helper class from JSON.Net to access the DeserializeAnonymousType() method that allows us to map a JSON string onto an anonymous type defined on the fly by passing an empty instance of it as the second argument of the call. Anonymous types are very handy when we need to define local data structures with no special behavior and without the burden of a full-blown class definition. Different anonymous type instances are matched across the code scope, and if they contain the same members (of the same type and in the same order), they end up being of the same type. DeserializeAnonymousType() returns a value of type T, where T is the same as the type of the template anonymous type instance we passed to it, which in this case is this new { body = "" } instance. The payload variable will therefore be of the same type, and this means that we are in fact defining the shape of the content we expect to find in the received data string. At this point, we can easily read inside the payload in a strongly typed manner and use its content to build a new object with the same shape but different content (new { body = body }), and use it to broadcast our response to all the connected clients.

    The approach we used when dealing with the serialization is just an example illustrating one option, and we could have taken several other approaches, but it should illustrate the kind of problems you might have to face when using the Persistent Connection API, and which direction to take when trying to solve them.

Let's now build a JavaScript client exchanging messages with the same shape as the ones we just defined.

  1. We first reference jQuery and SignalR using the following code:

    <script src = "Scripts/jquery-2.1.0.js"></script> <script src = "Scripts/jquery.signalR-2.0.2.js"></script>

  2. We then define our client logic with the following code:

    <script> $(function () { var c = $.connection('echo'); c.received(function(message) { console.log('Received: ' + message.body); }) .start() .done(function () { c.send({ body: 'hello' }); }); }); </script>

    This code is pretty simple. It's just using both the send() and received() methods we saw in the previous recipes of the article, making sure that received() is called before starting the connection and send() is used when the connection is ready.

We are ready to test our code by launching the project from Visual Studio and navigating to the index.html page, while opening the Developer Tools of the browser we are using to check the shape of the received message. If we open multiple tabs pointing at the same page, we'll see how the messages are broadcasted to all the already available clients as soon as they connect for the first time.

How it works...

What's more interesting is how we deal with the exchanged payloads, which are JavaScript objects with the same shape of the anonymous types inside the server-side OnReceived() method. We send an object like { body: 'hello' } and we expect to receive messages with the same shape. SignalR is smart enough to match these equivalent definitions when going from the server to the client, whereas it needs some help from us when going the other way round, as we saw when describing what we have to do to interpret the incoming payload in the OnReceived() method.

Exchanging messages between a server and a .NET client

SignalR's natural environment is the Web, that's why we tend to prefer the JavaScript client for our examples that illustrate its features. Nevertheless, the .NET client is as important and relevant as the JavaScript one, and it definitely deserves to be analyzed too. This last recipe of the article will be a translation of what we did in the previous recipe, but here the JavaScript client code will be replaced by C# code hosted in a console application. The server-side portion of this example will be the same as the one we wrote in the previous recipe, hence we'll avoid repeating the same code here and we'll be connecting to that application instead.

Getting ready

As already mentioned, we'll be connecting to the server we wrote in the previous recipe, so make sure you have that code ready and running before proceeding. Let's then create a console application project, naming it Recipe29, and then let's add to it the Microsoft ASP.NET SignalR .NET Client package from NuGet.

How to do it...

The Program class source code must be modified in the following manner:

  1. We first add the necessary using directives as follows:

    using System; using System.Threading.Tasks; using Microsoft.AspNet.SignalR.Client;

  2. We then apply a strategy to be able to use the async/await syntax for our asynchronous calls as follows:

    static void Main(string[] args) { Do().Wait(); } static async Task Do() { ... }

  3. Let's start writing the actual implementation of the Do() method by preparing the connection as follows:

    const string url = "http://localhost:14622/echo"; var connection = new Connection(url);

    The SignalR client library exposes a Connection type, which is the equivalent of the $.connection object we used with the JavaScript client. It has to be configured with an endpoint to target, represented by the URL we are passing as its only argument. The port number we specify (14622) must match the port number used to expose EchoConnection in the previous recipe. Please verify and fix it if it does not.

  4. We can now attach event handlers on the Received event member exposed by connection. In our case, we define just one handler in order to send to the standard output the message we will receive in response to our outgoing call:

    connection.Received += message => Console.WriteLine("Received: {0}", message);

    Received differs from the equivalent On() method from HubConnection because in this case we deal with a classic .NET event handler, while On() has the goal of registering a callback function to be called by name directly from the server. The more general-purpose approach of the Persistent Connection API fits nicely with the idiom exposed by a plain old .NET event handler.

    As for the JavaScript client, the declaration of these event handlers must be done before connecting to the server.

  5. Now we are ready to connect to our Hub using the following code:

    await connection.Start();

    This code is asynchronously initiating the connection and, as we already saw in the earlier recipes, we are waiting for its completion thanks to the await keyword.

  6. When the connection is ready, we can call the Send() method exposed by the Connection type and supply our payload to it as follows:

    connection.Send(new { body = "Hello" });

    The Send() method is very straightforward, and it's basically the same as the one we saw when discussing the JavaScript client. The supplied payload is an instance of an anonymous type, whose shape must match the one we are expecting to receive on the server side of the previous recipe, and you can easily verify that it does. In this way, we'll ensure that the server will be able to correctly understand what we are sending to it.

  7. We eventually make our code wait for the user to press Enter before exiting the application as follows:

    Console.WriteLine("Sending..."); Console.ReadLine();

There is something worth noting about the Received member: it does not conform to the traditional signature of an event handler. Usually, two arguments are expected as follows:

  • The sender of the event

  • A type derived from EventArgs that passes any context information

In the case of Received, the sender is not provided, and the context is in the form of a simple string containing the received payload. Should the server send a complex object, the Received event would be supplied with its JSON representation.

We are ready to test our code by launching the project from Visual Studio and observing the output displayed on the console window.

How it works...

What goes on behind the scenes is no different from what we have been describing earlier in this article, but there is something interesting to highlight about the way we called Send(). In fact, even if it's an asynchronous method and could therefore be awaited, in our code we are not waiting for its completion. Because of that, the final effect is something like what's shown in the following screenshot:

You can see that the Sending... message is printed out before the received payload, and that's because we did not wait for Send() to complete. We can modify our call on the Send() method to be like the following code:

await connection.Send(new { body = "Hello" });

In this case, the output will change, reflecting the fact that we used await to wait for the call to complete, and the two messages would be swapped.

It's also worth noting that the server payload is received as a string, whose content represents the JSON serialization of the object prepared on the server side. This illustrates the fact that, even if the type used to exchange messages is a simple string, a complex object is able to go through anyway, and it can be received and then properly deserialized if enough knowledge about its shape is available to the client.

Summary

In this article, we discussed the more low-level Persistent Connection API. We illustrated its peculiar features and differences when compared to Hubs.

Resources for Article:


Further resources on this subject:


SignalR Real-time Application Cookbook Use SignalR to create real-time, bidirectional, and asynchronous applications based on standard web technologies with this book and ebook
Published: April 2014
eBook Price: $29.99
Book Price: $49.99
See more
Select your format and quantity:

About the Author :


Roberto Vespa

Roberto Vespa has been passionate about programming computers since he was at high school, and he always wanted to do that for a living.

He has a degree in Electronic Engineering obtained in Italy, and has been working in the Information Technology industry since 1995, consulting on many different projects and for several customers. He is a software developer and architect with strong experience on the Windows platform, and in particular on the .NET Framework since Version 1.0, and on web technologies. He has always been working across a broad spectrum of responsibilities from distributed applications to complex user interfaces, from architecture and designing solutions to debugging server and client code, and from native Windows clients to web user interfaces.

He loves to learn, share, and communicate about technology. He wrote technical articles for an Italian magazine in the past, and now puts his effort into looking at the latest advances in programming or in contributing to open source projects such as ElmahR, a real-time error monitoring web dashboard built on top of SignalR. You can find out more about it at http://elmahr.apphb.com/.

Since 2011, he has been working in Switzerland where he lives with his wife, Cecilia, and their cats.

You can follow him on Twitter at @wasp_twit.

Roberto's blogs are at http://www.robychechi.it/roby.

Books From Packt


 SignalR: Real-time Application Development
SignalR: Real-time Application Development

ASP.NET 3.5 Application Architecture and Design
ASP.NET 3.5 Application Architecture and Design

ASP.NET 4 Social Networking
ASP.NET 4 Social Networking

ASP.NET 3.5 Social Networking
ASP.NET 3.5 Social Networking

ASP.NET MVC 1.0 Quickly
ASP.NET MVC 1.0 Quickly

 ASP.NET Data Presentation Controls Essentials
ASP.NET Data Presentation Controls Essentials

ASP.NET MVC 2 Cookbook
ASP.NET MVC 2 Cookbook

ASP.NET Site Performance Secrets
ASP.NET Site Performance Secrets


Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software