Adding and registering a persistent connection

In this first recipe of the chapter, 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");
            }
        }
    }

    We already described the usage of the OwinStartup attribute at the beginning of the book; therefore, we'll skip any details about that. 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 chapter, 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 as we already saw earlier in the book. 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 chapter. 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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.102.225