SignalR Real-time Application Cookbook

4.5 (2 reviews total)
By Roberto Vespa
  • Instant online access to over 7,500+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. Understanding the Basics

About this book

SignalR is a recent addition to ASP.NET, which allows you to add real-time functionalities to your applications. SignalR enables bidirectional communication between client and server over HTTP, transparently, and ensures you're always provided with the experience of a persistent connection.

SignalR Real-time Application Cookbook is a practical, hands-on guide that provides a number of clear step-by-step recipes that will gradually enable you to add SignalR as an innovative, effective, and useful item in your toolbox. This book will move from simple examples on to complex use cases, going through a comprehensive overview of the library. Other than helping out with the common tasks, at the end of the book you will find a set of ready-made solutions for more complex scenarios.

Publication date:
April 2014
Publisher
Packt
Pages
292
ISBN
9781783285952

 

Chapter 1. Understanding the Basics

In this chapter, we will cover:

  • Adding a Hub to an ASP.NET project

  • Adding a Hub to a self-hosting application

  • Connecting to a Hub from a JavaScript client

  • Connecting to a Hub from a .NET application

 

Introduction


SignalR is an amazing framework that delivers a real-time and bidirectional messaging platform. SignalR provides several options to reach its goal, but in this chapter we'll start simple and use the most basic API to set up a persistent and real-time channel: Hubs. A Hub is a special class that SignalR will expose to all the connected clients, allowing them to make Remote Procedure Calls (RPC) to it. Inside the Hub, the developer will also have a set of special objects to use in order to perform calls back onto the connected clients.

There is a very important detail to highlight: SignalR is composed of a server-side library and a set of client-side libraries. In every working solution, you will always need to use both; you will need to expose the server-side endpoints and connect to them using the most appropriate client library. SignalR will do the rest, and you will experience a very natural, simple, and bidirectional programming model.

All the recipes in this chapter will be classic "Hello World" applications. Nothing fancy or exciting will be happening, but all of them will clearly illustrate what can be achieved and how. The Adding a Hub to an ASP.NET project and Adding a Hub to a self-hosting application recipes will show you how to prepare a server portion of a SignalR application using the Hub type in different hosting contexts, whereas the Connecting to a Hub from a JavaScript client and Connecting to a Hub from a .NET application recipes will illustrate how to write client-side code to connect to it from different types of client processes. Each recipe has the goal to be fully functional, therefore all of them will in some way provide at least some hints about the missing counterparts. Server-side recipes will have minimal client code in place, and client-side ones will either contain a basic Hub to connect to or refer to one created earlier, but for all of them, the focus will remain on the actual topic of the recipe.

 

Adding a Hub to an ASP.NET project


SignalR sets a clear separation between the actual messaging runtime and the hosting environment. Although the host could be any plain old .NET-based process, the most natural context where you can add a SignalR Hub is inside an ASP.NET project, which is the topic of this recipe. Later in this chapter, we'll see how to host it in a different context.

This recipe will concentrate on the server-side; however, some minimal client-side code will also be added to be able to fully demonstrate a complete, although trivial, client-server connection.

Getting ready

There are three main types of ASP.NET projects:

  • A Web Forms application

  • An MVC application

  • A website

The process of creating them is a fairly common task, so we are going to skip the details. If you want more information, you can refer to the Appendix A, Creating Web Projects at the end of the book and check how to generate them step by step. In this recipe, we will be covering all of them at once, highlighting the points where there's some difference across those types.

Note

In order to show a complete sample for all three cases, the code that comes with this book will contain three separate projects, called Recipe01_WF (for the Web Forms sample), Recipe01_MVC (for the MVC project), and Recipe01_WS (for the website).

Before proceeding, please pick one of them and create your project in Visual Studio 2013.

How to do it…

We're ready to actually start adding the SignalR bits. Let's start with the Hub with the following steps.

From the Project menu, select Add New Item (you can also use the project context menu from Solution Explorer or the Ctrl + Shift + A keyboard shortcut), click on the Web folder, and then select the SignalR Hub Class (v2) template; specify EchoHub as the name and click on OK as shown in the following screenshot. Make sure you have selected the v2 Version because we want to target SignalR 2.0.

Visual Studio will add a new file called EchoHub.cs with some boilerplate code inside.

  1. Let's edit the file content to make it look like the following code snippet:

    using System.Diagnostics;
    using Microsoft.AspNet.SignalR;
    using Microsoft.AspNet.SignalR.Hubs;
    namespace Recipe01
    {
        [HubName("echo")]
        public class EchoHub : Hub
        {
            public void Say(string message)
            {
                Trace.WriteLine(message);
            }
        }
    }

    Tip

    Downloading the example code

    You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.

    The following lists the important points here:

    • The necessary using directives are listed at the top of the file.

    • The EchoHub class is derived from Hub, which comes from Microsoft.AspNet.SignalR.Hubs and makes the server-side SignalR API available to our class.

    • The class is marked with the HubName attribute, which allows us to give the Hub a friendly name to be used by the clients; if we don't use the HubName attribute, the Hub name will be the same as the class name (in this case, it would be EchoHub).

    • Our Hub contains a method called Say(). This is just a sample method we'll use to show how to expose Hub endpoints. On every call, it will just output the value of the message parameter in the debugger Output window, or in any trace listener we may want to configure.

    The class namespace is not so important. Here, I'm choosing the same name as the project name; it's the recommended way, but it does not have to be like that.

  2. From the Project menu, select Add New Item again, click on the Web folder, and then select the OWIN Startup class template. Specify Startup as the name and click on OK, as shown in the following screenshot:

    Visual Studio will add a new file called Startup.cs with some code inside it.

  3. Let's edit the file content to make it look like the following:

    using Microsoft.Owin;
    using Owin;
    [assembly: OwinStartup(typeof(Recipe01.Startup))]
    namespace Recipe01
    {
        public class Startup
        {
            public void Configuration(IAppBuilder app)
            {
                app.MapSignalR();
            }
        }
    }

The following lists the important points here:

  • SignalR 2.0 uses Open Web Interface (OWIN) for .NET as the standard interface between .NET web servers and web applications, enabling a level of indirection and abstraction that keeps your project from directly tying to any specific hosting platform. This is the technical foundation that actually enables SignalR to be hosted from both web applications and traditional .NET processes, as we'll see later.

  • Every OWIN application must have a Startup class that follows specific conventions. In particular, a Configuration() method with the signature shown in the preceding code must be made available.

  • The assembly-level attribute OwinStartup is there to declare that our Startup class will be used to bootstrap every OWIN-based asset contained in all the loaded assemblies; there are other ways to declare the right Startup class to load, but we'll see them in the future recipes.

  • Inside the Configuration() method, we start up SignalR using an appropriate extension method (MapSignalR()) made available by the SignalR core inside the Owin namespace; a call to the MapSignalR() method will expose an endpoint called /signalr, which the clients will use to connect to the server.

We're done! Our first SignalR Hub is ready to be called. However, as already mentioned, in order to see it in action, we need a client. Let's build one inside our web application using the JavaScript SignalR client.

Let's add a web page that we'll use as the place to put our basic client to test our Hub. This is where the recipe differs across the different project types. The most natural choices are as follows:

  • Web form for a Web Forms application: From the Project menu, select Add New Item, click on the Web folder, select the Web Form template (specifying, for example, index.aspx as the name), and click on OK.

  • Razor View for an MVC application: Let's first add a default controller named HomeController and then a view for its Index default action, which will be called index.cshtml. Please refer to the Appendix A, Creating Web Projects if you want more details about these steps.

  • HTML page for a website: From the Project menu, select Add New Item, click on the Web folder, select the HTML Page template (specifying, for example, index.html as the name), and click on OK.

Visual Studio will create the specified file with some basic HTML content. Those files will slightly differ according to the type you picked earlier, but for now we're just interested in the content of the <head> section, which we'll modify to make it look like the following code:

    <script src="Scripts/jquery-2.1.0.js"></script>
    <script src="Scripts/jquery.signalR-2.0.2.js"></script>
    <script src="/signalr/hubs"></script>
    <script>
        $(function () {
            var hub = $.connection.echo;
            $.connection.hub
                .start()
                .done(function () {
                    hub.server.say('Hello SignalR!');
                });
        });
    </script>

We basically kept what was there and then we just added a few <script> blocks. We'll go into detail about this portion in the Connecting to a Hub from a JavaScript client recipe. So, for any questions you might have about this code, please hold on for a while! The only thing we anticipate here is that the special /signalr/hubs endpoint does not correspond to any file that you'll find in the project; nevertheless, it's correct and will be explained later on.

We can now launch the application from Visual Studio: a browser window will open, the page will be loaded, and the Say() method of the EchoHub class will be executed as soon as the page is completely loaded in the browser. We can prove this by observing the effect of the Trace.WriteLine(message); line of code on the Output debug window, where the message will be printed.

How it works…

Let's review the main points of what we just did:

  • We added a Hub class. Any class available in the project that is derived from Hub is automatically discovered and exposed when SignalR is initialized calling MapSignalR in the Startup class.

  • The client page established a connection to our EchoHub using the JavaScript SignalR client library.

  • When the connection is ready, we make a remote call to the Say() method exposed by our EchoHub.

  • SignalR coordinates the two sides using the most appropriate connection strategy (more on that in future recipes), taking into account which is the HTTP server hosting the application and which web browser is used to run the client page; it gives us the feeling of a direct connection towards our server-side Hub, allowing us to call methods on it directly (the line hub.server.say('Hello SignalR!');).

There's more…

So far, we did not experience anything really special. We just performed a client-to-server call, which could have been done with plain old HTTP techniques. Nevertheless, we just laid the foundation for any SignalR Hub-based web application.

 

Adding a Hub to a self-hosting application


SignalR can be considered as a web framework because it's based on web technologies, such as HTTP and HTML5, but it can actually be used in the context of classic standalone processes without any relationship to browsers or web servers. This is possible thanks to the .NET client library for the client part, and to the self-hosting capabilities for the server part. The latter, in particular, is the subject of this recipe. It enables scenarios where the server-side portion of a SignalR application can live inside any hosting process, without requiring it to be an ASP.NET web application. In this recipe, we'll see how to host SignalR inside a simple console application, but any other .NET process would do. This way, we have a chance to use SignalR in scenarios where we do not have a proper web server available, or where thinking about an embedded SignalR makes sense.

Getting ready

Let's create a console application using the following steps:

  1. Navigate to File | New Project.

  2. Navigate to Installed | Visual C# in the dialog box and select the Windows folder.

  3. On the central panel of the dialog box, select Console Application, give it a name (Recipe02, in this case), and click on OK.

Visual Studio will add a Program.cs file containing the startup code for our application to the new project that we just created in Visual Studio 2013. For this recipe, we will add all our code to this file just after the Program class, whose static Main() method we'll be filling at the end of the recipe.

How to do it…

We're ready to actually start building our SignalR server. Visual Studio simplifies the process for web applications or websites, offering a series of code templates for Hub or Startup classes that we used in the previous recipe. But, for more general Windows applications, those templates are not available, and we'll have to undergo a slightly longer process. First, we'll need to add a reference to SignalR 2.0, which we can be easily found on NuGet, using the following steps:

  1. Select the Recipe02 project, and under the Project menu, click on the Manage NuGet Packages… entry.

  2. From the corresponding dialog box, let's do a search for the online packages using signalr self host as a filter condition. We should be presented with a results list like the following:

  3. Let's select the Microsoft ASP.NET SignalR Self Host package and then click on the Install button; this action will download and install all the packages we need to proceed with our application.

  4. We are ready to add some code. Let's start with our Hub by opening the Program.cs file and adding the following code just outside of the existing Program class:

    [HubName("echo")]
    public class EchoHub : Hub
    {
        public void Say(string message)
        {
            Trace.WriteLine(message);
        }
    }

    In order to compile the previous code, we'll have to add the following using directives at the top of the file:

    using System.Diagnostics;
    using Microsoft.AspNet.SignalR;
    using Microsoft.AspNet.SignalR.Hubs;

    The following lists the important points here:

    • The class EchoHub is derived from Hub, which comes from Microsoft.AspNet.SignalR.Hubs, and makes the server-side SignalR API available to our class.

    • The class is marked with the HubName attribute, which allows us to give the Hub a friendly name to be used from the clients; if we don't use the HubName attribute, the Hub name will be the same as the class name (in this case, it would be EchoHub).

    • Our Hub contains a method called Say(). This is just a sample method we'll use to show how to expose Hub endpoints. On every call, it will just output the value of the message parameter in the debugger Output window, or in any trace listener we may want to configure.

    Let's proceed with the rest of the code.

  5. Now we need to add a Startup class, as shown in the following code, to correctly bootstrap our SignalR Hub:

    class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.MapSignalR();
        }
    }

    The MapSignalR call will expose an endpoint called /signalr that the clients will use to connect to the server. In order to compile the code, we'll have to add the following using directive at the top of the file:

    using Owin;
  6. We're almost done. We just need to start up everything inside the Main() method mentioned earlier, which we now modify to make it look like the following code snippet:

    static void Main(string[] args)
    {
        using (WebApp.Start<Startup>("http://localhost:1968"))
        {
            Console.WriteLine("Server running!");
            Console.ReadLine();
        }
    }

    In order to compile the code, we'll have to add the following using directives at the top of the file:

    using System;
    using Microsoft.Owin.Hosting;

The following lists the important points here:

  • By calling WebApp.Start<Startup>("http://localhost:1968"), we are telling the self-hosting subsystem that it has to use our Startup class to initiate a SignalR endpoint and make it listen to the supplied URL. The chosen port (1968) is a random one. You could pick any other, provided you check your firewall when deploying your solution.

  • The resulting endpoint will of course expose the SignalR protocol, therefore only connections to it from a SignalR client would make sense and actually work.

  • When the initialization call has been completed, we print a message and then wait for someone to press Enter; this is important to keep our console application alive. Without it, the process would immediately end and the server would go away.

Our self-hosting process is now ready to be used. When launched, it will wait for clients to connect and call the Say() method on the EchoHub Hub. At each call, we would notice a Hello SignalR! message printed on the Output debug window by the Trace.WriteLine(message); call inside the Say() method.

We did not write any client code, but in self-hosting scenarios, it's not so common to have any client portion at all. Therefore, we'll end this recipe here. In the Connecting to a Hub from a .NET application recipe at the end of this chapter, we will be writing a standalone .NET client, and we'll be using it to connect to this server.

 

Connecting to a Hub from a JavaScript client


After having illustrated the two different ways we have to expose a server-side Hub let's now move on and see the client-side code in more detail.

During the Adding a Hub to an ASP.NET project recipe, we quickly used the JavaScript client library in order to demonstrate that our Hub was fully functional, but we did not go much into detail about it because we were concentrating on the server-side code. This recipe will fill this gap and give more clarity on how a JavaScript client is written. However, in order to make it fully functional, we will need a server-side portion; therefore, we'll be adding a basic Hub the same way we did for the Adding a Hub to an ASP.NET project recipe. Any specific detail about how to do it will be skipped because it's just an accessory to the real goal of this recipe, and we will just list the necessary steps. For any further clarification about that part, you can check the Adding a Hub to an ASP.NET project recipe.

Getting ready

Let's create a website where we'll be hosting our client. This is a common task, so we are going to skip the details. If you want more information about this, you can refer to Appendix A, Creating Web Projects at the end of the book.

How to do it…

We're ready to actually start adding what we need to build our SignalR client. We need to use the following steps:

  1. As we did in the Adding a Hub to an ASP.NET project recipe, we'll add a Hub called EchoHub and a Startup class. Here, we'll skip all the related details for brevity. Just make sure that the project ends up containing the same server-side code. These actions will download and add all the SignalR-related references, including the JavaScript client libraries.

  2. Let's add a web page to which we'll add our client. From the Project menu, select Add New Item, click on the Web folder, select the HTML Page template (specifying, for example, index.html as the name), and click on OK.

Visual Studio will create the specified file with some basic HTML content; let's edit it to make it look like the following:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script src="Scripts/jquery-2.1.0.js"></script>
    <script src="Scripts/jquery.signalR-2.0.2.js"></script>
    <script src="/signalr/hubs"></script>
    <script>
        $(function () {
            var hub = $.connection.echo;
            $.connection.hub
                .start()
                .done(function () {
                    hub.server.say('Hello SignalR!');
                });
        });
    </script>
</head>
<body>
</body>
</html>

We basically kept what was there and just added the highlighted <script> blocks that you can see in the previous code.

We can now launch the application from Visual Studio; a browser window will open and the index.html page will be loaded. Then we'll observe the code reaching the Trace.WriteLine(message); line inside the Say() method of the EchoHub class as soon as the page is completely loaded in the browser.

How it works…

Let's concentrate on our client page. The details are as follows:

  • The first relevant portion of code are the first two <script> blocks, where we reference jquery and jquery.signalR as JavaScript libraries. jQuery is necessary because the SignalR JavaScript client is actually a jQuery plugin, as the actual name of the library makes clear.

  • Our libraries are taken from the /scripts folder, where they have been placed by one of the NuGet packages installed as soon as we added our Hub. This package is actually called Microsoft ASP.NET SignalR JavaScript Client and can be installed in any ASP.NET application, even if the application does not contain any Hub. We'll see how this can be useful in future recipes, where we will be trying to connect to Hubs hosted in a different web application from the one containing the client.

  • The third <script> block refers to a dynamic endpoint (/signalr/hubs) exposed by the server portion because of the MapSignalR call from the Startup class, already explained in the previous recipes. It actually generates JavaScript code on the fly according to the available Hubs. In practice, the JavaScript proxies for our Hubs (in this case, the EchoHub Hub) are built on the fly by the server-side portion of SignalR as soon as this endpoint is hit, and they're sent to the client as JavaScript source code.

  • The last <script> block is where we actually connect to our Hub. Let's dig more into it. The details are as follows:

    • Our code is written inside a classic jQuery $(...); call, which actually ensures that our code is called when the page is fully loaded.

    • We first take a reference to our echo Hub, which is exposed by the $.connection.echo property generated by the dynamic endpoint that we just described.

    • Then we call the start() method exposed by the $.connection.hub member, which performs the actual connection to our server.

    • The start() call is asynchronous, and we have to make sure it has actually been completed before using any Hub; that's easy because start() returns a promise object containing a done() method to which we can pass a callback function, where we put our Hub-related code. This way, we are sure that SignalR will call our code when the Hub proxy is fully initialized and ready to be used.

    • Inside our callback function, we can use our Hub instance; in particular, it's the server member from which we are able to call any method exposed by the Hub. The hub.server.say('Hello SignalR!'); line of code will actually call the Say() method on our server-side Hub.

    • Note that say is written in lowercase here. Regardless of the actual name on the server-side Hub, in a JavaScript context, SignalR automatically generates camel case names in order to provide a more idiomatic JavaScript API.

When launching the application from Visual Studio, a browser window will open, the page will be loaded, and the Say() method of the EchoHub class will execute as soon as the page is completely loaded.

 

Connecting to a Hub from a .NET application


In the context of the Adding a Hub to a self-hosting application recipe, we already mentioned that SignalR can be used in the context of a generic standalone process, and we detailed how this can be leveraged for the server-side portion of an application. Thanks to the .NET client library, we can apply the same reasoning on the client side, enabling traditional Windows applications to connect to any SignalR server. In this recipe, we'll learn how to use the .NET SignalR client inside a simple console application. For the server portion to connect to, we'll make use of what we did in the Adding a Hub to a self-hosting application recipe, so please make sure you have the code from that recipe ready and fully working before proceeding.

Getting ready

Let's create a console application using the following steps:

  1. Navigate to File | New Project.

  2. Navigate to Installed | Visual C# in the dialog box and select the Windows folder.

  3. On the central panel of the dialog box, select Console Application, give it a name (Recipe04, in this case), and click on OK.

Visual Studio will add a Program.cs file containing the startup code for our application. For this recipe, we will add all our code to this file, which contains the following lines:

namespace Recipe04
{
    class Program
    {
        static void Main(string[] args)
        {
        }
    }
}

How to do it…

We're ready to actually start building our SignalR client. Visual Studio simplifies the process for web applications or websites, which are normally supposed to contain both server- and client-side portions; hence, the action of adding a Hub through the corresponding Visual Studio code template actually includes the JavaScript client portion too. When building a purely .NET client, we do not have a specific code template to use, and we have to resort to NuGet to import the appropriate package. This is done using the following steps:

  1. Select the Recipe04 project, and under the Project menu, click on the Manage NuGet Packages… entry.

  2. From the corresponding dialog box, perform a search for the online packages using signalr client as the filter expression. We should obtain a results list like the following:

  3. Select the Microsoft ASP.NET SignalR .NET Client package and then click on the Install button. This action will download and install all the packages that we need to proceed with our application.

  4. We are ready to add some code. Let's open the Program.cs file and modify the Main() method's body as follows:

    using System;
    using Microsoft.AspNet.SignalR.Client;
    
    namespace Recipe04
    {
        class Program
        {
            static void Main(string[] args)
            {
                var url = "http://localhost:1968";
                var connection = new HubConnection(url);
                var hub = connection.CreateHubProxy("echo");
                connection.Start().Wait();
                hub.Invoke("Say", "Hello SignalR!");
                
                Console.ReadLine();
            }
        }
    }

How it works…

  • Starting from the inside of the Main() method, the first line defines the address to which our client will try to connect to, and the second line actually instantiates a connection object pointing to that address; our client will expect to find a SignalR server listening at that position.

  • Then we use the connection object to create a proxy for the EchoHub Hub that we used so far when building our servers (the third line). In this recipe, we are using the one that we created in the Adding a Hub to a self-hosting application recipe, so we know from its code that it will be listening on port 1968, and it will expose our EchoHub Hub with the friendly name echo, which we supply as a parameter to the CreateHubProxy() method that will provide us with a proxy pointing to it.

  • We are now ready to perform the connection using the Start() method. Its return value is a task-derived object, which means its execution will be asynchronous; indeed, we are not allowed to use a Hub until the connection process has properly completed. That's why in this example we use the Wait() method to block our code until the connection is effectively ready.

  • When we are done with the Wait() call, we can safely address any method on our Hub proxy. We know that EchoHub exposes a Say() method, so we call it using Invoke, to which we pass the name of the method to call (Say()) and the list of the expected parameters (in this case, just one for the "Hello SignalR!" message argument).

  • The Console.Readline() method is there to prevent the process from exiting immediately.

That's it. If we now launch the Recipe 02 console application first and then the one we just built in this recipe (either from Visual Studio directly or from a console window), we should see the server application happily printing Hello SignalR! on the screen because of the call from our client.

Note

Pay attention; you have to keep the application's Recipe02 project open while Recipe04 is running. If you just debug Recipe02 and then stop the debugger to launch Recipe04, Recipe02 will be killed. There are several ways to achieve the right workflow. One of the simplest is to make Recipe02 the active project, start it without debugging (Ctrl + F5), and then make Recipe04 active and launch it, with or without debugging.

This recipe has completed our first showcase of SignalR features, and it allowed us to understand the basics of how it works and the general structure of any SignalR-based application. We also learned about the different types of hosting we can use and about the two client libraries available out of the box.

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.

    Browse publications by this author

Latest Reviews

(2 reviews total)
Good book that explains how to implement signal r from the practice.
Habe nichts an dem Kauf auszusetzen.
Book Title
Access this book, plus 7,500 other titles for FREE
Access now