itcamp 2012 - alessandro pilotti - web api, web sockets and rsignal
TRANSCRIPT
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Building modern web sites with ASP .Net Web API,
WebSockets and RSignal
Alessandro Pilotti
MVP ASP.Net / IIS
Windows Azure Insider
@alexpilotti
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development ITCamp 2012 sponsors
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development
• ASP.Net Web API
• SignalR
• WebSocket
Agenda
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development
• The web app designer’s holy grail:
– Reach the usability level of a desktop app
• The web app designer’s curse:
– Lack of standard API on the browser’s side
• Until recently the only way out was a RIA framework:
– Flash / Silverlight
What’s the deal?
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development
• HTML5 is changing the game
• Great set of new browser features: – Application cache
– Web storage
– WebSockets
– WebWorkers
– Geolocation
– Drag&Drop
– Multiple file uploads
– Inline SVG
– History management
– … and that Video thing
HTML5
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development
• Javascript is getting a huge boost – There’s more than meets the eye
– Its prototyping nature and flexibility is great • The rest sucks
• An enormous amount of frameworks are available today, e.g: – JQuery / JQuery UI
– Knockout.js
– Backbone.js
– Underscore.js
– History.js
– …And a gazillion more
Javascript?
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development
• Single Page Applications
– A single HTML is loaded in the browser
– History (aka back button) is managed via
Javascript
– Templates are used to load and render in the
DOM content on demand
• Some Ajax might be useful for that
– Offline usage
• Application cache
• Web storage
SPA
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development
• Web pages communicate with the server via asynchronous calls
– XmlHttpRequest (as in ajax)
– JSON serialization • Way faster than XML
• Originally decoded with “eval”
• Modern browsers provide native encoding / deconding – JSON.parse(…) / JSON.stringify(…)
– Even faster!
– RESTful APIs
– WebSockets • Where supported
And how do we access Data?
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development
• Faster web sites
• Lower traffic
• Clear separation
– UI
– Services / BL
• Enhanced testability
– Unit tests for the server API
– MVVM in Javascript (e.g. Knockout.js)
• Enhanced portability
– E.g. Mobile UI
Great advantages
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development
• ASP.Net Web API – Comes with MVC4
– Provides a new RESTful Web API framework
– ODATA support
– Very easy
– Great IoC support
– EF integration (DbDataController<T>)
– Can be also installed on MVC3 or Web Forms • Install-Package AspNetWebApi
• All the ASP.Net Stack is open source!! – http://aspnetwebstack.codeplex.com/
• Alternative: WCF – RESTful support
– More control • Complicated bindings configuration
ASP.Net Web API
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development
• Use of HTTP verbs:
– GET
– POST
– PUT
– DELETE
• Great for CRUD operations
• Errors use HTTP semantics
– E.g. not found => 404
• Uses custom routing
• A lot less bloated than SOAP
RESTful APIs
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development
Action HTTP verb Relative URI
Get a list of all products GET /api/products
Get a product by ID GET /api/products/id
Get a product by category GET /api/products?category=category
Create a new product POST /api/products
Update a product PUT /api/products/id
Delete a product DELETE /api/products/id
RESTful APIs example
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development
jQuery does all the dirty job, the result is neat and clean:
$.getJSON(
"api/products",
function(data) {
$.each(data, function(index, value) {
$("#products").append('<li>' + value.Name + '</li>');
});
});
jQuery example
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development
routes.MapHttpRoute(
name: "API Default",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
• Avoids conflicts with MVC routing
• Naming Convention
– GetAllProducts, DeleteProduct, etc
• Explicit action attributes:
– [HttpGet], [HttpPost], [HttpPut], [HttpDelete], [NonAction]
• User "api/{controller}/{action}/{id}” for RPC style routing
– Needs explicit verb attributes
ASP.Net Web API routing
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development
• ASP.Net Web API is based on a pipeline
• Inherit from DelegatingHandler to create
your handlers
– E.g. check an API key
• Add with:
– config.MessageHandlers.Add(new
ApiKeyHandler());
HttpMessageHandler
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development
• Open Data Protocol – A web protocol for querying and updating data
• Enable ODATA queries on your Web API – Just return an IQueriable<T>
• Examples – http://localhost:1702/api/Products?$filter=Enabled%2
0eq%20true
– http://localhost:1702/api/Products?$orderby=Name%20desc
– http://localhost:1702/api/Products?$filter=startswith(Name,’whatever')
ODATA + Web API
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development
• Great tool for troubleshooting
• curl -i -H "Accept: application/json"
http://localhost:1823/api/Products
• curl -i -H "Content-Type: application/json" -H
"Accept: application/json" -X POST -d
@data.json http://localhost:1823/api/Product
CURL
itcampro @ itcamp12 # Premium conference on Microsoft technologies
WEB API DEMO
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development
• A framework that provides some magic for: – Persistent connections
• LongPolling
• WebSockets
• Examples: chat, stock ticker updates
– Dynamic proxy generation for Javascript code • Hubs
– JSON serialization
• Asynchronous model
• Supports self hosting
• Unrelated to MVC or Web Forms
• Install-package SignalR – Or: https://github.com/SignalR/SignalR
SignalR
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development Long Polling
1. The client connects via HTTP 2. The server waits for available data 3. The server sends the response 4. Back to step one
A way to simulate push data connections
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development
public class MyConnection : PersistentConnection
{
protected override Task OnReceivedAsync(IRequest request, string connectionId, string data)
{
// Broadcast data to all clients
return Connection.Broadcast(data);
}
}
Routing setup in global.asax:
RouteTable.Routes.MapConnection<MyConnection>("echo", "echo/{*operation}");
Persistent connections (server)
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development
$(function () {
var connection = $.connection('/echo');
connection.received(function (data) {
$('#messages').append('<li>' + data + '</li>');
});
connection.start();
$("#broadcast").click(function () {
connection.send($('#msg').val());
});
});
Persistent connections (client)
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development
• Task OnConnectedAsync(IRequest request, string connectionId)
• Task OnReconnectedAsync(IRequest request, IEnumerable groups, string connectionId)
• Task OnReceivedAsync(IRequest request, string connectionId, string data)
• Task OnDisconnectAsync(string connectionId)
• Task OnErrorAsync(Exception error)
PersistentConnection API
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development
• Task Broadcast(object value)
• Task Send(string signal, object value)
IConnection API
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development
var context =
GlobalHost.ConnectionManager.
GetConnectionContext<MyEndPoint>();
context.Connection.Broadcast(message);
• Useful to send messages starting from a server action
External broadcasts
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development
public class Chat : Hub
{
public void Send(string message)
{
// Call the addMessage method on all clients
Clients.addMessage(message);
}
}
• Methods can have any name, the client resolves the names via proxy
• Clients is a dynamic object – addMessage is defined in Javascript!!
Hub (server)
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development
var chat = $.connection.chat;
// Declare a function on the chat hub so the server can invoke it
chat.addMessage = function(message) {
$('#messages').append('<li>' + message + '</li>');
};
$("#broadcast").click(function () {
// Call the chat method on the server
chat.send($('#msg').val())
.done(function() {
console.log('Success!');
})
.fail(function(e) {
console.warn(e);
});
});
// Start the connection
$.connection.hub.start();
Hub (client)
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development
• SignalR’s AspNetBootStrapper defines – [assembly:
PreApplicationStartMethod(typeof(AspNetBootstrapper),
"Initialize")]
– Initialize calls: RouteTable.Routes.MapHubs();
• Mapping the /signalr route
• No need for:
– Explicit global.asax route mapping
– Web.config settings
Look Mama, no global.asax routes
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development
var context =
GlobalHost.ConnectionManager.
GetHubContext<MyHub>();
context.Clients.say(message);
External broadcasts
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development
• appcmd.exe set config /section:serverRuntime /appConcurrentRequestLimit:100000
• In %windir%\Microsoft.NET\Framework\v4.0.30319\aspnet.config
– maxConcurrentRequestsPerCPU="20000”
• In %windir%\Microsoft.NET\Framework\v4.0.30319\Config\machine.config
– <processModel autoConfig="false" requestQueueLimit="250000" />
IIS setup for high loads
itcampro @ itcamp12 # Premium conference on Microsoft technologies
SIGNALR DEMO
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development
• TCP/IP communication style model
– Handshake resembles HTTP
• Interoperable
• Standard W3C (still in draft)
– Older browsers support old versions
• Bidirectional communications
• Supports cross domain access!
WebSockets
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development
Request:
GET /mychat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat
Sec-WebSocket-Version: 13
Origin: http://example.com
Response:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
Handshake
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development
• Url: ws://yourhost/etc – wss: when used with SSL/TLS
var socket = new WebSocket('ws://game.example.com:12010/updates');
socket.onopen = function () {
setInterval(function() {
if (socket.bufferedAmount == 0)
socket.send(getUpdateData());
}, 50);
};
Javascript
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development
• IE 10
• Chrome 4
• Firefox 4
• Safari 5
• Opera 11
• Server: IIS 8
Minimum requirements
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development
• Proxies tipically don’t recognize WebSocket
traffic
• By using SSL/TLS the problem is mitigated
– Client uses HTTP CONNECT in this case
Proxy support
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development IIS 8 – enable WebSockets feature
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development WCF 4.5 – HTTP Activation
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development WCF 4.5
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Mobile &
Development
• Install-Package Microsoft.WebSockets
RouteTable.Routes.Add(new ServiceRoute("connect", new WebSocketServiceHostFactory(), typeof(GameService))); public class GameService : WebSocketService { private static GameServer server = new GameServer(); private GameConnection connection; public override void OnOpen() { string nickname = QueryParameters["nickname"]; int gameSize = int.Parse(QueryParameters["gamesize"]); connection = server.JoinGame(this, nickname, gameSize); } public override void OnMessage(string message) { connection.ProcessCommand(message); } protected override void OnClose() { if(connection != null) connection.Disconnect(); } } }
In ASP.Net – updated support
itcampro @ itcamp12 # Premium conference on Microsoft technologies
WEBSOCKETS DEMO
itcampro @ itcamp12 # Premium conference on Microsoft technologies
Q & A