SignalR Real-time Application Development


SignalR: Real-time Application Development Utilize real-time functionality in your .NET applications with ease Einar Ingebrigtsen BIRMINGHAM - MUMBAI SignalR: Real-time Application Development Copyright © 2013 Packt Publishing All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews. Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, nor Packt Publishing, and its dealers and distributors will be held liable for any damages caused or alleged to be caused directly or indirectly by this book. Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information. First published: June 2013 Production Reference: 1310513 Published by Packt Publishing Ltd. Livery Place 35 Livery Street Birmingham B3 2PB, UK. ISBN 978-1-78216-424-1 www.packtpub.com Cover Image by Abhishek Pandey (abhishek.pandey1210@gmail.com) Credits Author Einar Ingebrigtsen Reviewers Gustavo Armenta Roar Flolo Acquisition Editor Martin Bell Commissioning Editor Ameya Sawant Technical Editors Joyslita Dsouza Veronica Fernandes Veena Pagare Project Coordinator Joel Goveya Proofreader Stephen Silk Indexer Monica Ajmera Graphics Ronak Dhruv Production Coordinator Arvindkumar Gupta Cover Work Arvindkumar Gupta About the Author Einar Ingebrigtsen has been working professionally with software since 1994—ranging from games development on platforms such as Playstation, Xbox, and the PC, to enterprise line of business application development, which he has been working on since 2002. He has always kept the focus on creating great products with great user experiences, putting the user first. Einar is a Microsoft MVP awardee five years in a row, awarded for his work in the Silverlight space with projects such as Balder, a 3D engine for Silverlight. Today Einar runs a company called Dolittle with partners, doing consultancy and building their own products with their own open source projects at the heart of what they do (http://github.com/dolittle). Among the clients that Dolittle has been involved with for the last couple of years, include NRK (largest TV broadcaster in Norway), Statoil (Norwegian oil company), Komplett (largest e-commerce in Norway), and Holte (leading Norwegian developer for construction software). Additionally, Einar loves doing talks at the user groups and conferences, and has been a frequent speaker at Microsoft venues talking about different topics, the last couple of years talking mostly about architecture, code quality, and cloud computing. It might sound like a cliché, but seriously, without my wife this book could not have happened. Her patience with me and her support is truly what pretty much makes just about anything I turn into a reality. So, Anne Grethe, thank you! I'm also blessed with kids with great patience while I have much going on, but most of all, thanks to them for keeping me playful! I'd also like to thank my colleagues who have been kind enough to not point to the fact that I've had too much going on in the period of writing this book, with crazy mood-swings. I'll be sure to buy a round the next time we're having a company get together. About the Reviewers Gustavo Armenta (Mexico) is an employee at Microsoft Main Campus located in Redmond which is very near to Seattle, WA. His current project is SignalR. He spends a good deal of his time with his team members: Damian Edwards (Australia), David Fowler (Barbados), Stephen Halter (US), Taylor Mullen (US), Abhishek Nanda (India), Xiaohong Tang (China), and Jorge del Conde (Mexico). Gustavo published a blog entry about how to use SignalR the day after the team released the first version of SignalR. The blog was visited by thousands of developers, and a few of them asked questions about it. He was surprised when his blog was used as reference to explain on Wikipedia what SignalR is. Then, he received an e-mail originating from the blog: Ameya Sawant (India) an editorialist for Packt Publishing who invited him to review a new book on the topic. Gustavo accepted the offer. He started working with Joel Goveya (India), project coordinator for Packt Publishing, and Einar Ingebrigtsen (Norway), the author of this book. To complete this story, we would need to know the location and country of origin of one more person—you, the reader! As you can realize, I feel very fulfilled with the experiences my professional career is providing me, both in knowledge and lifestyle. Thanks mom and dad, for giving me two amazing siblings. Roar Flolo started his career as a game developer at Funcom in 1993. Since then he has worked on most game platforms developing real-time 3D graphics, character animation, tools and asset pipelines, AI, networking, physics integration, and vehicle physics. He worked freelance since 2005 until he co-founded Pixelwerk AS in 2012, where he's currently a CTO working on exciting technologies such as real-time 3D, mobile development, augmented reality, web solutions, WebGL, and graph databases. www.PacktPub.com Support files, eBooks, discount offers and more You might want to visit www.PacktPub.com for support files and downloads related to your book. Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.PacktPub. com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at service@packtpub.com for more details. At www.PacktPub.com, you can also read a collection of free technical articles, sign up for a range of free newsletters and receive exclusive discounts and offers on Packt books and eBooks. http://PacktLib.PacktPub.com Do you need instant solutions to your IT questions? PacktLib is Packt's online digital book library. Here, you can access, read and search across Packt's entire library of books. Why Subscribe? • Fully searchable across every book published by Packt • Copy and paste, print and bookmark content • On demand and accessible via web browser Free Access for Packt account holders If you have an account with Packt at www.PacktPub.com, you can use this to access PacktLib today and view nine entirely free books. Simply use your login credentials for immediate access. Table of Contents Preface 1 Chapter 1: Revitalizing the Rich Client 7 The Emperor's new clothes 7 The good old terminal 8 X server 9 Remote desktop 10 Rich clients 11 The Web 12 Full duplex on the Web 12 Events 13 Comet 13 Hand-rolling it all 14 Why? 14 Now what… 14 Think different 14 Summary 15 Chapter 2: Persistent Connections 17 Where are we going? 17 The persistent connection 17 Summary 32 Chapter 3: Hubs 33 Moving up one level 33 Summary 40 Chapter 4: Groups 41 Getting specific with groups 41 Summary 51 Table of Contents [ ii ] Chapter 5: State 53 Becoming stateful 53 Summary 57 Chapter 6: Security 59 Becoming private 59 Summary 70 Chapter 7: Scaling out 71 Scaling out 71 SQL Server 72 Redis 76 Azure 78 Summary 81 Chapter 8: Monitoring 83 Looking under the covers with monitoring 83 Fiddler 83 Performance counters 85 Summary 89 Chapter 9: Hosting a server using OWIN 91 Self hosting 91 Summary 97 Chapter 10: WinJS and Windows 8 99 WinJS 99 Summary 107 Index 109 Preface Users are becoming more advanced, technology is moving forward at a rapid pace, and we have more options with cloud computing than ever before. All of this calls for thinking differently about how we make our applications work smarter, deliver faster, and not let the user poll for information but rather have data and changes pushed directly to the user without the user having to interact with anything. With demand on functionality and a world with many platforms, we as developers, are constantly seeking out new ways to make it easier to target all of these; the Web has become the result of this search with HTML5 and JavaScript engines becoming much faster and more widely available. We are relying more and more on the aging HTTP protocol to be our vessel for information to the user. SignalR provides the ability to let you as a developer not have to think about all the details of creating applications that meet all these requirements, and not only for web applications. The purpose of this book is to provide you with a step-by-step guide for starting with SignalR, and also to give an insight into why you would want to SignalR enable your application. Throughout the book we will be building an application with a server component and multiple clients—Web,.NET, and Windows8/WinJS. What this book covers Chapter 1, Revitalizing the rich client, will teach you that in order to get started with SignalR and real-time web applications, it is important to understand the motivation behind wanting to have such a technology and approach to application development. Chapter 2, Persistent Connections, will help you understand that at the core of SignalR sits something called PersistentConnection; this is where everything starts. In this chapter you will learn how to get started with it in the backend and consuming it in the frontend. Preface [ 2 ] Chapter 3, Hubs, will move you up one abstraction layer from PersistentConnection to something called Hubs. A Hub provides a more natural abstraction for most scenarios. A Hub is easier to write and easier to consume. Chapter 4, Groups, will explain grouping. Sometimes you want to filter messages so that you can better control which clients get what messages. Grouping is a way in SignalR to accomplish this; you will learn how to deal with this on the server and the client. Chapter 5, State, will explain you that in addition to sending messages between client and server that are very explicit, you sometimes need to have accompanying metadata or additional data that is cross-cutting. In this chapter, you will learn how state can go back and forth with messages. Chapter 6, Security, is about how every application needs to take security into consideration. In this chapter, you will learn techniques that you can apply to your SignalR code to secure messages. Chapter 7, Scaling Out, will show you how to scale out and be able to deal with building applications that scale on multiple servers, not only in an on-premise environment but also in Microsoft's Windows Azure cloud. Chapter 8, Monitoring, will show you how to monitor messages and look at possible performance bottlenecks. Debugging is part of the everyday life of a developer and, of course, it applies to development with SignalR. Chapter 9, Hosting a Server Using OWIN, will look at how to self host a simple console application using OWIN. Open Web Interfaces for .NET is an abstraction-enabling web framework to be agnostic about the underlying platform. Chapter 10, WinJS and Windows8, will port our web client to be a Windows 8 store application through the usage of WinJS. What you need for this book In order to get started with SignalR you will need either Visual Studio 2010, any edition, although NuGet, which you also need, is not supported out of the box for the express edition. You can also use Visual Studio 2012; in fact, the book has been written using it. With Visual Studio 2012, the express edition has NuGet out of the box. For NuGet you can go to http://www.nuget.org for more information. As a side note, it is also possible to use Mono for development and Xamarin Studio, if you are on a different platform such as Linux or Mac. The code is the same—you just need to manage the references differently. SignalR has Mono packages on NuGet. Preface [ 3 ] Who this book is for This book is primarily for .NET developers. It also targets those .NET developers who are working on web solutions with HTML and JavaScript. Conventions In this book, you will find a number of styles of text that distinguish between different kinds of information. Here are some examples of these styles, and an explanation of their meaning. Code words in text are shown as follows: "We can include other contexts through the use of the include directive." A block of code is set as follows: Var connection = new Connection (http://localhost:1599/chat); Any command-line input or output is written as follows: $("#sendButton").click(function() { chat.server.send($("#messageTextBox").val()); $("#messageTextBox").val(""); New terms and important words are shown in bold. Words that you see on the screen, in menus or dialog boxes for example, appear in the text like this: "clicking the Next button moves you to the next screen". Warnings or important notes appear in a box like this. Tips and tricks appear like this. Reader feedback Feedback from our readers is always welcome. Let us know what you think about this book—what you liked or may have disliked. Reader feedback is important for us to develop titles that you really get the most out of. Preface [ 4 ] To send us general feedback, simply send an e-mail to feedback@packtpub.com, and mention the book title via the subject of your message. If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, see our author guide on www.packtpub.com/authors. Customer support Now that you are the proud owner of a Packt book, we have a number of things to help you to get the most from your purchase. 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. Errata Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you find a mistake in one of our books—maybe a mistake in the text or the code—we would be grateful if you would report this to us. By doing so, you can save other readers from frustration and help us improve subsequent versions of this book. If you find any errata, please report them by visiting http://www.packtpub. com/submit-errata, selecting your book, clicking on the errata submission form link, and entering the details of your errata. Once your errata are verified, your submission will be accepted and the errata will be uploaded on our website, or added to any list of existing errata, under the Errata section of that title. Any existing errata can be viewed by selecting your title from http://www.packtpub.com/support. Piracy Piracy of copyright material on the Internet is an ongoing problem across all media. At Packt, we take the protection of our copyright and licenses very seriously. If you come across any illegal copies of our works, in any form, on the Internet, please provide us with the location address or website name immediately so that we can pursue a remedy. Preface [ 5 ] Please contact us at copyright@packtpub.com with a link to the suspected pirated material. We appreciate your help in protecting our authors, and our ability to bring you valuable content. Questions You can contact us at questions@packtpub.com if you are having a problem with any aspect of the book, and we will do our best to address it. Revitalizing the Rich Client This chapter walks you through the history of application development, especially web applications. The topics covered are: • Why do we need to think differently about our applications and how they relate to a server • The different techniques that can be used without something like SignalR • The protocols and techniques SignalR uses to do what it is doing • Why do we need something like SignalR • What UX improvements one could make in an application when using SignalR At this stage the developer should have the basic knowledge of how SignalR works, and what he/she needs to rethink when designing applications that have a persistent connection to the server. The Emperor's new clothes As with fashion, it sometimes feels a lot like history repeats itself in our industry as well. It seems that we are going full circle with how software should be architected. I guess this comes from having pretty much the same goal; software solutions that scale for lots of users, and keep data as updated as possible for all users. What this means is that we probably want to have a shared data source that all clients can get their data from. It also means that we need some kind of network connection for the clients to connect to the centralized data source. The clients are typically distributed across multiple offices, maybe even different geolocations. With different geolocations often comes the challenge of different network types and bandwidth. Revitalizing the Rich Client [ 8 ] The good old terminal Before we get to the cool things, it's important to gain some perspective on the problem we're trying to solve. It is, in fact, an old problem dating back to the early days of computers. Back in the 1970s, in the early computer days, it was quite common to see terminals much like the following one in offices: The nature of these terminals was to be as primitive as possible. They didn't do any computation, nor did they hold any state. The terminal only reflected what the server wanted the terminal to show on screen, so in many ways they were just really fancy television sets. Any input from the users' keyboard was sent to the server and the server would interpret the user input, update the user's terminal session, and send the screen update back to the terminal as shown in the following figure: Chapter 1 [ 9 ] Process user input Application logic Update terminal session User input Terminal Server This model proved very helpful, technically, as we developers had everything on our server and didn't have to think about any rich clients holding state making it all the more complex. We only needed to scale the server and deal with potentially multiple servers and keep them in sync or work against a centralized data source. But it didn't prove useful for good user experience. The terminals were limited to text only, and the types of user interfaces one could create were limited, often ending up being very data-centric and keyboard-friendly. X server In 1984, the X Window System (commonly known as X11) was introduced, originating from the Massachusetts Institute of Technology (MIT); a graphical user interface system. With it came a network protocol for enabling networked computers to connect to servers in a similar fashion to the terminals of the 70s, and a big step up from the text-based terminal with its graphical capabilities. Revitalizing the Rich Client [ 10 ] As with the terminal solution, the users' input would be sent to a server and the software the user was using would in fact run on that very server, and the result in the graphical user interface would then be sent back to the client machine. Again, leaving the client to be rather dumb and passive. User’s workstation X Server Network Remote machine Keyboard Mouse Screen X client (xterm) X client (browser) X Client (up2date) Remote desktop Meanwhile in 1998, in the world of Windows, Windows NT 4 got a post-fixed edition of the operating system "Terminal Server Edition". With this edition, Microsoft introduced a new protocol called Remote Desktop Protocol (RDP). It allowed the ability for a client to view another computer's desktop and with NT 4 Terminal Server, the operating system would be able to host multiple desktops for multiple users at the same time. From this remote desktop, clients could then launch any applications they wanted that existed on the server they had connected to. As with the good old terminals, the client computer did not need to be very capable. In fact, this gave birth to an industry, thin-client computers, capable of connecting to an RDP-enabled server. Chapter 1 [ 11 ] Server Thin Client Thin Client Thin Client Rich clients By having the software running on the server, one puts tremendous pressure on the server(s) and its capability. It must be capable of handling all of the users and their input, which leads to the need for a certain computational power, of course, depending on the application itself. Sometimes it does not make sense to have it all running on a server. It might not be worth it for your particular application, it might be too costly to try to scale for what you need. It could also be a question of responsiveness; your app might need more responsiveness to make sense to the user. But stepping into the world of a rich, stateful client normally increases the complexity of our solutions. Of course, depending on what we're making. If we do not have concurrency issues, or data not becoming stale, we don't necessarily have anything that is needing to be solved. Unfortunately, for most line of business software out there, this is not the case. We need to take into consideration that there might be multiple users out there and decide on how to deal with it. We can go down the optimistic path and pretend users seldom run into each other's data and we just overwrite any data that might have been modified while we were making a change to the same piece of data. Or we could go pessimistic and not allow that at all, giving us an exceptional state in the application that we often let our users deal with. One way we can let rich clients deal with this and pretty much leave the problem behind is to use something like TCP sockets and communicate between the clients as they are changing any state. The other respective clients can then pick up the change and alter their own state before the user gets to the point of saving, maybe even notify the user that someone else has modified it. Revitalizing the Rich Client [ 12 ] The Web And here we are again, back to the dumb client. Our web browsers have served as the passive client for years. The model is frighteningly similar to the terminal solution of the 70s; a dumb client capable of taking input and rendering whatever comes across the network and a rich server doing all of the work. Hypertext Transfer Protocol (HTTP) is what makes up the Web. It surfaced for the first time in 1991 and basically describes a protocol for sending a request to a server and the server sending a response. The protocol is stateless and you will need to keep state either on the server or on the client. Within the protocol today, there are well-defined methods that can be used, such as POST, GET, PUT, DELETE, and more. These methods let us describe what we are doing. Although a well-defined and rich protocol, it has nothing defined in it to let clients be persistently connected. You can read more about HTTP at http://en.wikipedia.org/wiki/Http. With web browser capabilities increasing over time, we've watched them go from very passive to rich clients. The mid 2000s gave us the buzz often referred to as Web 2.0 and AJAX; Asynchronous JavaScript and XML. At the core of this JavaScript is something called XHR (XMLHttpRequest), making it programmatically accessible to call the server from the client without user interaction. The technique leverages HTTP and you find that instead of getting whole web pages, you get parts, or just the data and put the data into the already rendered web page. You can find more details about AJAX at http://en.wikipedia.org/wiki/Ajax_(programming). Modern web applications are turning into a hybrid of rich client and thin client; very capable but they shouldn't do it all—we do need server-side logic. A true step in the right direction would be letting the client be good at what it is good at and likewise, with the server, the correct step would be separating the concerns of the two tiers. Now that we have all of this power in the browser, we quickly run into similar problems we have with regular rich clients; state on the client. Full duplex on the Web With the evolution going backwards into the future, meaning that we are now at the point where we need the same kind of connectivity we needed for rich desktop applications, the demand is that applications live on the Web. With the users, demands come technical challenges. The Web was not built for this; the Web is based on a request/response pattern. The browser goes to a specific URL and a server spits out a response. Chapter 1 [ 13 ] One of the things that the W3C organization has done to accommodate this need is the standardization of something called WebSocket; full-duplex communication channels over a single TCP connection. A very good initiative is something that will be supported by all browser vendors as well as web servers. The challenge with it getting a broad adoption is on the infrastructure that makes up the Web. The entire infrastructure has been optimized for the request/response pattern, and steady connections making a point-to-point connection between two computers, and all of a sudden scalability becomes an issue. So, in many cases, it might not be the best solution. Events Another initiative was by Opera, the Norwegian browser vendor called server-sent events, now being standardized by W3C. This gives us the opportunity to push events from the server to any clients that are connected. Combining it with the regular HTTP request/response, we are able to meet the requirement of rich applications. You can read more about server-sent events at http://en.wikipedia.org/wiki/Server- sent_events. Comet Not changing the subject just yet, but a technique called Comet has also been applied with great success. The basis of this is to utilize something called long polling HTTP requests. One opens an HTTP request to the server from the client; the server does not return anything until it has something to return, like an event that happens on the server. When the response has been received, the client starts a new long polling connection and keeps on doing so forever. This simulates a full-duplex connection, and scales very well with the existing infrastructure of the Web. You can read more about Comet http://en.wikipedia.org/wiki/Comet_(programming). Begin HTTP Web Request Handle Response Wait for server-side events Handle Event Server-side event occurs HTTP Request long polling HTTP Response Revitalizing the Rich Client [ 14 ] Hand-rolling it all You're probably getting where I am going with this. The techniques described previously, are some of the techniques SignalR utilizes. Surely, the techniques and standards are well known and nothing holds you back from working with them directly. But this is where SignalR comes in and saves the day. Why? The most important thing to ask in software development is why? (http://en.wikipedia.org/wiki/5_Whys). Why do we want all this? What is it that we're really trying to solve? We're trying to make software more collaborative, and make users work together without having artificial technical limitations to this collaboration. In fact, why not have any change done occur in real time with all users collaborating? Now what… SignalR represents an abstraction for all the techniques that it supports today, and with it also the extensibility of supporting future techniques that might come along. Built in sits a fallback mechanism which enables it to pick the best solution for your app, based on the server and connecting client capabilities. In addition SignalR provides great mechanisms for scaling out in a multi-server environment, enabling applications to be blissfully unaware of which server they are running on and just work with the same abstraction as if it was only one server. Think different Apple coined the phrase "Think Different" back in 1997. The phrase in itself forces you to think differently, since it is grammatically incorrect. With all the asynchronous operations and events going into a technology like SignalR, one really has to think in different ways, but different in a good way. Good for the users, as we are now forced to create user experiences that are non-blocking. Of course, you as a developer can force locks onto the users, but I would argue it would be easier not to and rather approach building the user interface in different ways. For instance, one of the things we tend to build into our apps is the notion of concurrency and stale data. We don't want to run the risk of two users updating exactly the same data and one client not having the updated data from the other user. Often, we leave this so our users get bizarre error messages that they usually won't understand. A better solution would be to have all of the data on all user screens be updated as they are looking at it, maybe even make them aware in a subtle way of any changes that happened from the other user(s). Chapter 1 [ 15 ] Summary The world of software development is in my opinion a very fun place to be, with a lot of things happening all the time. Looking back at the last 30-40 years, we've come a long way; although, we do tend to go around in loops, and that comes, in my opinion, from us trying to solve the same problem in the same manner every time with the modern techniques available at that time. With today's technologies and users demands, there are great opportunities to change the pattern a bit and do things differently—think differently about the problems and make things even more user friendly. SignalR represents one of these opportunities. It holds an abstraction that makes it a lot easier to embrace the different approaches that we can have when creating great user experience. It does, at the same time, represent robustness and with Microsoft committing resources to the project, it now also represents a commitment from one of the largest software vendors in the world. Another aspect SignalR represents is Microsoft's growing commitment to open source. All of the source code for SignalR is freely available, and they are also accepting outside commits. In the next chapter we'll get started with SignalR and the entry level for getting started, that is PersistentConnection. With this, you will be able to keep a connection open persistently between the client and the server. Persistent Connections This chapter will cover the basics of getting a client connected to the server and how messaging works. The topics covered include: • Setting up a web application with SignalR • Exposing a persistent connection to the server • Consuming the connection in a .NET client • Consuming the connection in a JavaScript client • Enabling WebSockets on Windows Server 2012 At this stage the developer should be able to have two client types and a server connected together. Where are we going? The remainder of the book will try to keep to the narrow path of developing iteratively on the same application; a Chat application with a web client, a .NET console client, and a Windows 8 WinRT client all working with the same server. We will also go into how to self-host SignalR in your own app for any clients to connect to, without having to have a web server installed and configured. The persistent connection This chapter will start with showing the simplest construct that SignalR provides; PersistentConnection. A PersistentConnection provides a simple abstraction for sending data back and forth between a client and a server. Persistent Connections [ 18 ] The process is the same for Visual Studio 2010 and 2012, but the samples in this book use Visual Studio 2012. You will however need to have NuGet installed. If you haven't, go to http://www.nuget.org and install it by clicking on the large Install NuGet button. 1. Let's start by creating a new project in Visual Studio. 2. Select the regular ASP.NET Empty Web Application project template situated under Visual C# | Web. Give it a name, SignalRChat. Chapter 2 [ 19 ] 3. We're going to pull SignalR in from NuGet. Right-click on the References node in your SignalRChat project. 4. From the Manage NuGet Packages window, select Online in the tree to the left and type Microsoft.AspNet.SignalR in the search box in the upper-right corner of the window. Persistent Connections [ 20 ] 5. Now that we have a basic web application, we will need to configure SignalR by registering a route in ASP.NET. In order to do that, we will need a Global Application Class (Global.asax) in the Web project. We add it by right-clicking on the project again and selecting Add | New Item. In the dialog, select Global Application Class found under the Web category. 6. We won't be needing most of what comes out of the template, so we can strip it down to only have the Application_Start method. 7. Also, we won't be needing all of the namespaces imported at the top, so strip it down to System, System.Web, System.Web.Routing, and Microsoft. AspNet.SignalR. Chapter 2 [ 21 ] 8. The only configuration we need at this stage is to add a route to the ASP.NET routing mechanism that associates http://:port/chat with your ChatConnection class. Your file should look as follows: 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. Persistent Connections [ 22 ] 9. Now we will create the ChatConnection class we mapped previously by adding a simple class, which will be our PersistentConnection for the chat. Right-click on the SignalRChat project and select Add | New Item. In the dialog, chose Class and give it the name ChatConnection.cs. 10. The class represents the connection, but we don't need anything in it at this point, so we'll just leave it empty for now. Chapter 2 [ 23 ] 11. That's it for now for the server-side part of the solution. We'll need an HTML page and some JavaScript to connect to the server and get chatting. Add an HTML page to the Web project and name it index.html. 12. In the HTML file, we will need to add the necessary script imports. You can drag the file you want from the scripts folder onto the code editor at the right place within the element, or just type it out. 13. First we need to add jQuery, so any version of jQuery higher than 1.6 will do: 14. Then we need to add the SignalR script that got added through NuGet: Persistent Connections [ 24 ] 15. Now we have enough to get started and we can add a new 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 that we implemented in Chapter 1, Revitalizing the Rich Client, for PersistentConnection altogether. Chapter 3 [ 37 ] 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("Connected\n"); }); 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(""); }); Hubs [ 38 ] 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: Chapter 3 [ 39 ] 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: Hubs [ 40 ] 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 filter out messages so you only get messages relevant for your context. Groups in the next chapter will cover this, groups is the technique used in SignalR to accomplish this. Groups This chapter will cover how you can group connections together and target specific groups when sending messages. The topics covered include: • Establishing groups on the server • Sending messages from the client to specific groups At this stage, the developer should be able to create groups and put connections into these groups. Getting specific with groups Many scenarios require you to not broadcast to everyone, and be more specific in who receives the message. SignalR provides an abstraction for these called groups. Groups hold connections that will receive messages. The API for sending messages is just the same, but you just choose to go to a specific group instead of going to everyone. For our chat applications we want to use groups to create chat rooms, specific groups which will receive chat messages that none of the other rooms/groups will receive. In order to get this working we will need to change our application slightly: 1. First we will need a class to manage the chat rooms that get created by any clients so that we keep track of them for any other clients that connect. Groups [ 42 ] 2. Right-click on the project and navigate to Add | New Item. In the dialog box, choose Class and give it the name ChatRooms.cs. 3. Basically, this class will just hold a list of strings that represent the different chat rooms by name for now: Static List _rooms = new List(); 4. We then want to just add the ability to add a chat room and get all the available chat rooms, and also check if a room already exists. By default, we will also add a well known chat room called Lobby. The class should look as follows: Chapter 4 [ 43 ] The line at the top of the class, Static List _rooms = new List(); is using an the built-in List, which is not thread-safe. This means that you can run into exceptions if you have two users joining a chat room at the same time. There are implementations out there that deal with this, and a quick search on the phrase ConcurrentList C# will yield a few options. Also, there is a SynchronizedCollection<> type found in System.Collections.Generics after adding a reference to System. ServiceModel that can be used. Groups [ 44 ] 5. Now, let's go back to the Hub Chat.cs that we created in Chapter 3, Hub. We will need to add some new functionality to this class, and also change some existing functionalities to make it support chat rooms. Let's start by adding a method that we can call from the client to create a chat room: 6. Next, we want to add is support for clients to be able to join a room and receive any messages published to it. This is where we use the Groups property from the Hub and just add the connection of the client connected to the group with the same name as the room we want to join: With that the client will only receive messages for the groups it is a part of and none of the others. 7. Now that we have a subsystem for dealing with rooms, and clients can connect to those rooms, we want to be able to tell the clients that are getting connected which rooms are available. On the Hub there is a virtual method, OnConnected(), which we can override for getting notified when a client connects. There are also methods to know when clients disconnect and reconnect. But for now we only need the OnConnected() method. In this method, we basically get all the rooms that have been created and send them off to the client that got connected using the Caller property on the Clients property which is sitting on the Hub: Chapter 4 [ 45 ] Your Hub should now look as follows: 8. Moving to the index.html file of your web application, we want to make some changes and add some new features. Let's start by altering the look of our app and introduce a list of available chat rooms as well as a way of adding a chat room. We will wrap it all up nicely in a table: Groups [ 46 ] 9. We will then continue by introducing a variant that holds the current chat room; we will put it the beginning of our script block and initialize it with Lobby as our default chat room: 10. Now we want to take the code that adds a message to the chatWindow textbox and put it into a function we can reuse: 11. Then we will need a function that can take a string with the chat room name and add it to the