>sddconf.com/brands/sdd/library/signalr.pdfinstall-package microsoft.aspnet.signalr add a startup...
TRANSCRIPT
© 2010 RoCk SOLiD KnOwledge Ltd.
SignalR
Kevin Jones
@kevinrjones
http://www.github.com/kevinrjones
© 2010 RoCk SOLiD KnOwledge Ltd.2
Why Async?
Why SignalR?
SignalR low level
Hubs
Dependency Injection
Deferred work
Agenda
© 2010 RoCk SOLiD KnOwledge Ltd.3
Asynchronous applications i
Building event driven asynchronous applications is 'easy'
User clicks on button
Event fires
Use Ajax to call back to server
Update UI if/when server returns
© 2010 RoCk SOLiD KnOwledge Ltd.4
Asynchronous applications ii
However that covers only one scenario
What about server push?
What about client to client communication
Client could poll
This has issues
What if no data is available?
How long should the poll interval be
Connection has to be managed
© 2010 RoCk SOLiD KnOwledge Ltd.5
Async code in the browser
Can use the Xml Http Request object (xhr)
Typically wrap in jQuery
$.ajax({type: 'post',url: '/Todo/Update',data: getData(options),success: function () {
alert('done');},contentType: 'application/json'
});
© 2010 RoCk SOLiD KnOwledge Ltd.6
Using the browser
Better techniques
Long polling
Forever frame
Server Sent Events
Web Sockets
© 2010 RoCk SOLiD KnOwledge Ltd.7
Long Polling
Open a connection to the server
Keep the connection open waiting for data
Wait for server to send data
Connection will eventually timeout
Re-open connection
© 2010 RoCk SOLiD KnOwledge Ltd.8
Forever Frame
Create an iFrame
Frame opens connection to server
Send data to the frame
Uses chunked encoding so data size does not need to be known
© 2010 RoCk SOLiD KnOwledge Ltd.9
Server Sent Events
New standard
Like web sockets but one way only
Server -> Client
Appear as JavaScript events in the browser
© 2010 RoCk SOLiD KnOwledge Ltd.10
Web Sockets
Implemented in modern browsers
2-way communication over sockets
Needs server support
Coming in Windows 8
© 2010 RoCk SOLiD KnOwledge Ltd.11
Enter SignalR
Made for ASP.Net
Server and client side libraries
Open source
Available on GitHub and Nuget
Wraps all the previous issues
© 2010 RoCk SOLiD KnOwledge Ltd.12
SignalR usage
Can work at a low level
Can use the hubs feature
© 2010 RoCk SOLiD KnOwledge Ltd.13
Installing
Install via NuGet
Install-package Microsoft.AspNet.SignalR
Add a startup class
[assembly: OwinStartup(typeof(TheatreBookingWeb.Startup))]namespace TheatreBookingWeb{
public class Startup{
public void Configuration(IAppBuilder app){
app.MapSignalR();}
}}
© 2010 RoCk SOLiD KnOwledge Ltd.14
Low level API - PersistentConnection
PersistentConnection
Various methods that are called asynchronously
public class SimpleConnection : PersistentConnection{protected override Task OnConnectedAsync(IRequest request,
string connectionId){...}protected override Task OnDisconnectAsync(string connectionId) {...}protected override Task OnErrorAsync(Exception error) {...}protected override Task OnReconnectedAsync(IRequest request,
IEnumerable<string> groups, string connectionId) {...}
protected override Task OnReceivedAsync(IRequest request, string connectionId, string data){...}
}
© 2010 RoCk SOLiD KnOwledge Ltd.15
Low level API - PersistentConnection
Derive class from PersistentConnection
Called asynchronously
Connection.Broadcast to all listeners
Conection.Send to specific listener
public class SimpleConnection : PersistentConnection{
protected override Task OnReceivedAsync(IRequest request, string connectionId, string data)
{return Connection.Broadcast(data);
}}
© 2010 RoCk SOLiD KnOwledge Ltd.16
Hub model
Nobody uses PersistentConnections
Use 'Hubs' instead
Hubs provide an easier model than PersistentConnections
No routing to set up
Provides a generated proxy
© 2010 RoCk SOLiD KnOwledge Ltd.17
Defining a Hub
Derive from Hub base class
public class TheatreBookingHub : Hub{
© 2010 RoCk SOLiD KnOwledge Ltd.18
Hub methods
Can define methods on the hub
public class TheatreBookingHub : Hub{
public void BookSeat(string row, int seatNumber, bool booked){}
}
© 2010 RoCk SOLiD KnOwledge Ltd.19
Hub members
Caller and Clients
Caller is the current executing browser
Clients are all the connected clients
public class TheatreBookingHub : Hub{
public void GetInitialData(){
Caller.initializeTheatre(Theatre);}
public void BookSeat(string row, int seatNumber, bool booked){
Theatre.UpdateSeat(row, seatNumber, booked);Clients.updateTheatre(Theatre);
}}
© 2010 RoCk SOLiD KnOwledge Ltd.20
Generates JavaScript
Proxy generated from the C#
Referenced from the browser
<script type="text/javascript" src="/signalr/hubs"></script>
'virtual' URL
Can be changed by adding a route
© 2010 RoCk SOLiD KnOwledge Ltd.21
Generated JavaScript
/// <reference path="jquery-1.6.2.js" />(function ($, window) {
/// <param name="$" type="jQuery" />"use strict";
// ...// Create hub signalR instance$.extend(signalR, {
theatreBookingHub: {_: {
hubName: 'TheatreBookingHub',ignoreMembers: ['bookSeat', 'getInitialData', 'namespace',
'ignoreMembers', 'callbacks'],connection: function () { return signalR.hub; }
},
bookSeat: function (booked, row, seatNumber, callback) {return serverCall(this, "BookSeat", $.makeArray(arguments));
}}
});
© 2010 RoCk SOLiD KnOwledge Ltd.22
Provide corresponding code in client
Client can call methods on the hub
Hub can call methods on the client
$(function () {theatre = $.connection.theatreBookingHub;
theatre.server.updateTheatre = function (data) {updateModel(data);
};
theatre.client.initializeTheatre = function(data) {viewModel = new TheatreViewModel(data, theatre);updateUI(viewModel);
};
$.connection.hub.start(function () {theatre.getInitialData();
});});
© 2010 RoCk SOLiD KnOwledge Ltd.23
Hub return types
Anything returned from Hub method is serialized to the caller
Caller returns a jQuery deferred
theatre.getInitialData().done(function (theatreData) {
theatre.initializeTheatre(theatreData);});
© 2010 RoCk SOLiD KnOwledge Ltd.24
Creation semantics
Hub is created for each call
Don't maintain state in the hub
© 2010 RoCk SOLiD KnOwledge Ltd.25
Sending from outside a Hub
May want to call clients when not in a hub
public class Notifier{
public void Notify(string message){
var context = GlobalHost.ConnectionManager.GetHubContext<TheatreHub>();
context.Clients.All.Tick();}
}
© 2010 RoCk SOLiD KnOwledge Ltd.26
Using IRegisteredObject
public class BackgroundUptimeServerTimer : IRegisteredObject{
private readonly IHubContext _uptimeHub;private Timer _timer;
public BackgroundUptimeServerTimer() {_uptimeHub = GlobalHost.ConnectionManager.GetHubContext<MyHub>();StartTimer();
}private void StartTimer() {
_timer = new Timer(BroadcastUptimeToClients, null, 2000, 1000);}private void BroadcastUptimeToClients(object state) {
_uptimeHub.Clients.All.Tick();}
public void Stop(bool immediate) {_timer.Dispose();
HostingEnvironment.UnregisterObject(this);}
}
© 2010 RoCk SOLiD KnOwledge Ltd.27
Register It
public class WebApiApplication : System.Web.HttpApplication{
protected void Application_Start(){
GlobalConfiguration.Configure(WebApiConfig.Register);FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);RouteConfig.RegisterRoutes(RouteTable.Routes);BundleConfig.RegisterBundles(BundleTable.Bundles);HostingEnvironment.RegisterObject(new BackgroundUptimeServerTimer());
}}
© 2010 RoCk SOLiD KnOwledge Ltd.28
Register a Client Callback
Before the hub starts
$.connection.kelloHub.client.tick = function() {console.log("tick");
};
© 2010 RoCk SOLiD KnOwledge Ltd.29
Can also return Task<T>
Can do async work
public Task<Theatre> GetInitialData(){
return Task.Factory.StartNew(() =>{
// Don't do this in the real worldThread.Sleep(500);return Theatre;
});}
© 2010 RoCk SOLiD KnOwledge Ltd.30
Other HTTP data
Context data member of type HubCallerContext
public class HubCallerContext{
public string ConnectionId { get; private set; }public IRequestCookieCollection RequestCookies { get; private set; }public NameValueCollection Headers { get; private set; }public NameValueCollection ServerVariables { get; private set; }public NameValueCollection QueryString { get; private set; }public IPrincipal User { get; private set; }
}
© 2010 RoCk SOLiD KnOwledge Ltd.31
Client Side Configuration
Can configure the client
$.connection.hub.start( { transport: ['webSockets', 'longPolling'] });
© 2010 RoCk SOLiD KnOwledge Ltd.32
Connection Lifetime Events
The client fires events at start, stop etcstarting
received
connectionSlow
reconnecting
reconnected
stateChanged
disconnected
$.connection.hub.stateChanged(function(oldState, newState) {console.log(oldState, newState);
});
© 2010 RoCk SOLiD KnOwledge Ltd.33
Handling Errors
Can log errors on the client
// on the servervar hubConfiguration = new HubConfiguration(); hubConfiguration.EnableDetailedErrors = true; app.MapSignalR(hubConfiguration);
$.connection.hub.error(function (error) { console.log('SignalR error: ' + error)
});