- •Contents at a Glance
- •Introduction
- •Who should read this book
- •Assumptions
- •Who should not read this book
- •Organization of this book
- •Finding your best starting point in this book
- •Conventions and features in this book
- •System requirements
- •Code samples
- •Notes on the version
- •Installing the code samples
- •Using the code samples
- •Acknowledgments
- •Errata & book support
- •We want to hear from you
- •Stay in touch
- •HTTP operations
- •Polling: The answer?
- •Push: The server takes the initiative
- •WebSockets
- •Server-Sent Events (API Event Source)
- •Push today
- •The world needs more than just push
- •What does SignalR offer?
- •Two levels of abstraction
- •Supported platforms
- •OWIN and Katana: The new kids on the block
- •Installing SignalR
- •Implementation on the server side
- •Mapping and configuring persistent connections
- •Events of a persistent connection
- •Sending messages to clients
- •Asynchronous event processing
- •Connection groups
- •The OWIN startup class
- •Implementation on the client side
- •Initiating the connection by using the JavaScript client
- •Support for older browsers
- •Support for cross-domain connections
- •Sending messages
- •Receiving messages
- •Sending additional information to the server
- •Other events available at the client
- •Transport negotiation
- •Adjusting SignalR configuration parameters
- •Complete example: Tracking visitors
- •Project creation and setup
- •Implementation on the client side
- •Implementation on the server side
- •Server implementation
- •Hub registration and configuration
- •Creating hubs
- •Receiving messages
- •Sending messages to clients
- •Sending messages to specific users
- •State maintenance
- •Accessing information about the request context
- •Notification of connections and disconnections
- •Managing groups
- •Maintaining state at the server
- •Client implementation
- •JavaScript clients
- •Generating the proxy
- •Manual generation of JavaScript proxies
- •Establishing the connection
- •Sending messages to the server
- •Sending additional information
- •Receiving messages sent from the server
- •Logging
- •State maintenance
- •Implementing the client without a proxy
- •Complete example: Shared drawing board
- •Project creation and setup
- •Implementation on the client side
- •Implementation on the server side
- •Access from other threads
- •External access using persistent connections
- •Complete example: Monitoring connections at the server
- •Project creation and setup
- •Implementing the website
- •System for tracing requests (server side)
- •System for tracing requests (client side)
- •External access using hubs
- •Complete example: Progress bar
- •Project creation and setup
- •Implementation on the client side
- •Implementation on the server side
- •Multiplatform SignalR servers
- •SignalR hosting in non-web applications
- •SignalR hosting in platforms other than Windows
- •Multiplatform SignalR clients
- •Accessing services from .NET non-web clients
- •Consumption of services from other platforms
- •Growing pains
- •Scalability in SignalR
- •Scaling on backplanes
- •Windows Azure Service Bus
- •SQL Server
- •Redis
- •Custom backplanes
- •Improving performance in SignalR services
- •Server configuration
- •Monitoring performance
- •Authorization in SignalR
- •Access control in persistent connections
- •Access control in hubs
- •Client authentication
- •An extensible framework
- •Dependency Injection
- •Manual dependency injection
- •Releasing dependencies
- •Inversion of Control containers
- •Unit testing with SignalR
- •Unit testing of hubs
- •Unit testing persistent connections
- •Intercepting messages in hubs
- •Integration with other frameworks
- •Knockout
- •AngularJS
- •Index
- •About the author
Optional changes in configuration (web.config)
For the tracing system to capture all the requests made to the website, whether or not they are processed by ASP.NET, it is a good idea to add the following configuration to the web.config file:
<configuration>
...
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"></modules> </system.webServer>
</configuration>
Note that this configuration will make the performance at the server even worse.
System for tracing requests (client side)
Spying page (spy.html)
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"> <head>
<title>Spying requests</title>
<script src="Scripts/jquery-1.6.4.min.js"></script>
<script src="Scripts/jquery.signalR-2.0.0.min.js"></script> </head>
<body>
<h1>Requests log</h1> <ul id="requests"></ul> <script>
$(function () {
var connection = $.connection("/spy"); connection.received(function (data) {
$("#requests").append("<li>" + data + "</li>");
});
connection.start();
});
</script>
</body>
</html>
External access using hubs
If we use hubs, the procedure is similar to what we saw earlier: in the process via which we want to be in contact with clients connected to a hub, we will use the global configuration object GlobalHost. Through its ConnectionManager property, we will obtain a reference to the hub.
Persistent connections and hubs from other threads Chapter 6 |
111 |
www.it-ebooks.info
The only difference compared to the procedure that we would carry out with persistent connections is that here we will obtain the reference to the hub using the GetHubContext() or
GetHubContext<T>() methods.
protected void BtnShutdown(object sender, EventArgs e)
{
var hubcontext = GlobalHost.ConnectionManager
.GetHubContext<Chat>();
hubcontext.Clients.All
.SendMessage("The system is shutting down!");
... // Code
}
In the preceding example, we have used the generic method GetHubContext<T>() to obtain the reference using strong typing, although we could have also done it referencing the hub through a character string:
var hubcontext = GlobalHost.ConnectionManager
.GetHubContext("Chat");
In either case, the methods return an instance of IHubContext, through which we can access the functionalities for sending information and managing groups available in hubs (see Figure 6-4).
FIGURE 6-4 Members of the IHubContext interface.
As you can easily guess, the Clients property, of the IHubConnectionContext type, is the gateway to recipient selection methods, discussed in Chapter 5, although it is more limited. For example, because we will use this interface from other processes, we will not have properties such as Caller or Others, which make sense only when the code is inside a hub and it is being executed as a consequence of the reception of a message from a client. However, we will find other useful selectors such as All, AllExcept(), Client(), or Group() to specify the recipients of any code invocation on the client side:
hubContext.Clients.Group("jedis").Alert(
"I felt a great disturbance in the force"
);
On its part, the Groups property allows managing the members of groups of SignalR clients, through its Add() and Remove() methods.
hubcontext.Groups.Add(lukeConnectionId, "jedis");
112 Chapter 6 Persistent connections and hubs from other threads
www.it-ebooks.info
Complete example: Progress bar
To better illustrate the operation and possibilities of external access to hubs or persistent connections, we will present the complete development of a system that notifies the progress of expensive processes in real time, as shown in Figure 6-5.
FIGURE 6-5 Progress bars operating.
In this case, we will have a client page from which we will use jQuery to launch an AJAX request to a costly process written inside an ASPX page. There will be notifications of the progress in real time from inside this process, and this will be displayed as a progress bar over the page.
Project creation and setup
For the purpose of creating the application that we will develop over the following pages, it is necessary to first create a project of the “ASP.NET Web Application” type from Visual Studio 2013 and then select the “Empty” template to create a completely empty project2. The version of the .NET Framework used must be at least 4.5.
After we have created it, we must install the following package using NuGet:
PM> install-package Microsoft.AspNet.SignalR
2 In Visual Studio 2012, we can achieve the same goal by creating a project from the template “ASP.NET Empty Web Application.”
Persistent connections and hubs from other threads Chapter 6 |
113 |
www.it-ebooks.info
Implementation on the client side
HTML markup (progress.html)
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"> <head>
<title>Progress bar</title>
<script src="Scripts/jquery-1.6.4.min.js"></script>
<script src="Scripts/jquery.signalR-2.0.0.min.js"></script> <script src="/signalr/js"></script>
<script src="Scripts/progressbar.js"></script>
<link rel="stylesheet" href="styles/progressbar.css"/> </head>
<body>
<div id="progressBarContainer"> <div id="progressBar"></div>
</div>
<input type="button"
id="start" value="Start" disabled="disabled" /> <div id="result" style="display: none;"></div>
</body>
</html>
Styles (Styles/ProgressBar.css)
#progressBarContainer { width: 400px; height: 18px;
border: 1px solid black; padding: 2px;
margin: 20px 0 20px 0;
}
#progressBar { width: 0px; height: 18px;
background-color: blue; margin: 0;
overflow: hidden; text-align: center; color: white; font-family: arial; vertical-align: middle; font-size: 14px;
}
#result {
border: 1px solid black; background-color: yellow; padding: 10px 10px 0 10px; margin-top: 10px;
}
114 Chapter 6 Persistent connections and hubs from other threads
www.it-ebooks.info