- •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
Receiving messages sent from the server
When methods of the client side are invoked from the server, we can capture these calls using the On() method as follows:
proxy.on("ShowAlert", function(msg) { alert(msg);
});
The first parameter supplied to this method is the name of the event or action invoked from the server, specified as a case-insensitive character string. The second one is the code to be executed, in the form of an anonymous function, with the parameters that have been sent to it from the remote end.
Complete example: Shared drawing board
In this example, we will use hubs to implement a simplified version of a shared drawing board system, with the purpose of showing how some of the concepts presented in this chapter work in practice.
Users will be able to draw freely on the canvas, and their actions will be visible to the other connected clients in real time. Furthermore, we will allow selecting the stroke color and erasing the entire drawing board at any moment. Each point drawn is stored at the server in a buffer so that the first thing that new clients receive is a full copy of the content of the drawing board at the time of their connection.
The result we want to obtain is shown in Figure 5-18.
96 Chapter 5 Hubs
www.it-ebooks.info
FIGURE 5-18 Shared drawing board.
Project creation and setup
For the purpose of creating the application that we will develop over the following pages, it is necessary first to create a project of the “ASP.NET Web Application” type from Visual Studio 2013 and then to select the “Empty” template to create a completely empty project4. The version of .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
4 In Visual Studio 2012 we can achieve the same goal by creating a project from the template “ASP.NET Empty Web Application.”
Hubs Chapter 5 |
97 |
www.it-ebooks.info
Implementation on the client side
HTML markup (drawingboard.html)
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"> <head>
<title>Drawing board</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/DrawingBoard.js"></script> <style>
div { margin: 3px; }
canvas { border: 2px solid #808080; cursor: default; } </style>
</head>
<body>
<div>
<div>
<label for="color">Color: </label> <select id="color"></select>
</div>
<canvas id="canvas" width="300" height="300"></canvas> <div>
<button id="clear">Clear canvas</button> </div>
</div>
</body>
</html>
Scripts (Scripts/DrawingBoard.js)
$(function () {
///////////////////////////////////////////////////////////////
// Standard drawing board functionalities
///////////////////////////////////////////////////////////////
var colors = ["black", "red", "green", "blue", "yellow", "magenta", "white"]; var canvas = $("#canvas");
var colorElement = $("#color");
for (var i = 0; i < colors.length; i++) { colorElement.append(
"<option value='" + (i + 1) + "'>" + colors[i] + "</li>"
);
}
var buttonPressed = false; canvas
.mousedown(function () { buttonPressed = true;
})
.mouseup(function () { buttonPressed = false;
})
98 Chapter 5 Hubs
www.it-ebooks.info
.mousemove(function (e) { if (buttonPressed) {
setPoint(e.offsetX, e.offsetY, colorElement.val());
}
});
var ctx = canvas[0].getContext("2d"); function setPoint(x, y, color) {
ctx.fillStyle = colors[color-1]; ctx.beginPath();
ctx.arc(x, y, 2, 0, Math.PI * 2); ctx.fill();
}
function clearPoints() {
ctx.clearRect(0, 0, canvas.width(), canvas.height());
}
$("#clear").click(function () { clearPoints();
});
///////////////////////////////////////////////////////////////
// SignalR specific code
///////////////////////////////////////////////////////////////
var hub = $.connection.drawingBoard;
hub.state.color = colorElement.val(); // Accessible from server var connected = false;
//UI events colorElement.change(function () {
hub.state.color = $(this).val();
});
canvas.mousemove(function (e) {
if (buttonPressed && connected) { hub.server.broadcastPoint(
Math.round(e.offsetX), Math.round(e.offsetY)
);
}
});
$("#clear").click(function () { if (connected) {
hub.server.broadcastClear();
}
});
//Event handlers
hub.client.clear = function () { clearPoints();
};
hub.client.drawPoint = function (x, y, color) { setPoint(x, y, color);
};
hub.client.update = function (points) { if (!points) return;
for (var x = 0; x < 300; x++) { for (var y = 0; y < 300; y++) {
Hubs Chapter 5 |
99 |
www.it-ebooks.info