Embrace HTTP with ASP.NET Web API
Transcript of Embrace HTTP with ASP.NET Web API
OOo Seagulls
Embrace HTTP with ASP.NET Web API
@filip_woj
www.strathweb.com
www.climaxmedia.com
What is ASP.NET Web API?
New Microsoft framework (RTM August 2012) for building HTTP services & applications
Aimed at simplyfing and standardizing HTTP area on the MS stack (see: WCF / ASMX / MVC / HttpHandlers)
Supports both REST and RPC style services
Open source!
beta in Feb 2012, RC in June 202 open source, just like Mvc, Entity Framework, part of azure i'm part of web api advisory board, assembled by Dan Roth from Microsoft, we meet every 2 weeks and discuss the new development ideas & general direction of the product, chief architect on the project is Henrik Nielsen, who in the early 1990s at CERN in Geneva, co-authored the HTTP spec and co-created th world wide web with Tim Berners Lee and the team
But it's Microsoft!
From: Scott Hanselman's ONE ASP.NET talk at aspconf 2012
ASP.NET has a bad reputation, as being an unnecessary abstraction over the web and being HEAVY MVC has changed that a bit, but still the perception remains especilly now with the rise of new sexy technologies such as node.js or earlier rails i'd like to show you that MS can also make stuff that's good for the web, and lightweight
Web API origins
HTTP in WCF
WCF REST starter kit
WCF Web API
finally adopted some concepts from ASP.NET MVC
the root for HTTP services in the MS stack lies in WCF, and was very poor, with complex configuration, a lot of angle bracket coding and lots of runtime errors this evolved with a few out of band releases such as REST starter kit, and eventually became WCF Web API WCF Web API was already open source then WCF and ASP.NET teams were merged and the result was Web API, as it adopted some concepts from MVC this lowers the barriers of entry for MVC developers, who'd instantly be familiar with the Web API way of building services because they know it from MVC
A mix of WCF Web API & MVC
from WCF Web API:- content negotiation- message handlers- REST & dispatching based on HTTP verbs code based configuration
content negotiation so the process of determining the response media type based on request message and opposite determining how to read the payload of the incoming request message handlers which run first and last in the stack and allow you to work with raw HTTP objects RESTful approach (as opposed to traditional RPC) the configuration process of Web API is based on how configuration was done in WCF web api and does not require XML files
A mix of WCF & MVC
from MVC:- model binding concept- controller based approach & RPC- routing- filters
the concept of model binding. While Web API does model binding completely differently than MVC, conceptually the task is the same controller centric approach, where each resource (also called API endpoint) is a controller ASP.NET routing; the routetable has been ported so that it can work outside of ASP.NET as well filters which run before and after an action dependency injection was already supported in WCF Web API, but they way it's implemented, almost mirrors how it's done ine MVC
here is the problem naming things is difficult, and in the case of Web API it creates lots of problems
ASP.NET Web API
The name creates lots of misconceptions
ASP.NET: it doesn't require neither ASP.NET, nor IIS to run
Web API: it's an HTTP framework, that can do much more than "just" API
Web API can be hosted in IIS, on top of ASP.NET but it's not a requirement Web API is a fully fledged framework, not just API tool. You can do whatever you'd expect from a web framework including handle binary files, handle state if needed, even serve HTML files with Razor engine
How can it work without ASP.NET/IIS?
Web hosting: ASP.NET & IISOWIN (i.e. Katana)
Self hosting: (using WCF hardened core)WPFWindows serviceconsole app, any other .NET app
Memory hosting: whole pipeline running in memory
3 hosting options web hosting is on top of ASP.NET and can be in IIS but it doesn't have to, it can also be hosted with any OWIN (open web interface for .NET) implementation such as Katana. I blogged about that self hosting means spinning up a web server inside of the managed process we are running (using WCF hardened core which wraps around httplistener). This can be done from any .NET app memory hosting means running th whole pipeline in memory without using netowrk hardware. You can create an instance of HttpServer and send data from HttpClient directly to it in memory
does not have the baggage of .NET 1.1 on whch Web Forms and MVC are built!
OK, but why would I need it?
New HTTP object model
Work with HTTP concepts
HTTP as a fully fledged *application* protocol
Facilitates both REST & RPC
Async from top-to-bottom
new HTTP programming model has been introduced in .NET 4.5, but Web API team backported a lot of the stuff to .NET 4.0 replaces old stuff from .NET 1.1 and System.Web, which started to show its age, and a lot of its concepts were synchronous and string based HTTP as a first class citizen; you get to embrace HTTP and you get a lot of things for free such as caching at various intermediary levels. You also don't have to reinvent the wheel with operation statuses and such with REST you follow the standards client and server work with same objects whole pipeline is async (as opposed to MVC or other frmwks). In MVC controllers are async but not pipeline. This means it scales well
NancyFX, ServiceStack built around IhttpHandler and are fully synchronous
Async examples
Handlers:
Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken);Filters:
Task ExecuteActionFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func continuation);Formatters:
Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext);Task ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger);
symmetrical between client and server pretty much everything you can imagine about HTTP from headers, through body content to response & request themselves are strongly typed no static configuration fully asynchrnous not just for sending messages, but even for tasks such s reading the request.response body very flexible in terms of extending media type support
New HTTP object model
Strongly typed HttpResponseMessage
Stronglytyped HttpRequestMessage
Strongly typed Headers
Strongly typed HttpContent
No more angle brackets coding & magic strings
Asynchronous API
Client-server symmetry
symmetrical between client and server pretty much everything you can imagine about HTTP from headers, through body content to response & request themselves are strongly typed no static configuration fully asynchrnous not just for sending messages, but even for tasks such s reading the request.response body very flexible in terms of extending media type support
HTTP status codes
1xx Informational
2xx Successful
3xx Redirection
4xx Error on the client side
5xx Error on the server side
HTTP headers request
Request headers (selected)Accept, Accept-Language, Accept-Encoding
Authorization, Cache-Control, Range
If-Match, If-Modified-Since, If-Range
Content headers (selected)Allow, Content-Encoding, Content-Language
Content-Length, Content-Type, Expires
Last-Modified
HTTP headers response
Response headers (selected)Accept-Ranges, Connection
Cache-control, Date, Etag
RetryAfter, Warning, Location
Content headers (selected)Allow, Content-Encoding, Content-Language
Content-Length, Content-Type, Expires
Last-Modified
RPC
/api/GetTeams
/api/GetTeam?id=1
/api/GetPlayersByTeam?id=1
/api/AddTeam
/api/UpdateTeam
/api/UpdateTeam?id=1&name=Leafs
/api/DeleteTeam?id=1
traditional model, familiar from perhaps ASMX or MVC call server methods by name gets messy
is shit
REST
representational state transfer
architecture for building systems by Roy Fielding
advantages:statelesscachabilityhypermedia driven (client needs to know one link, usually)scalabilityeverything addressable with URI
REST is probably the most verused buzz word in the web world but has several advantages, mainly cause it's standard STATELESS no session, so for example as an authenticated user, you have to sign requests and reauthenticate each time true REST should be hypermedia driven with a one entry point to the application and navigational properties you build around HTTP VERBs NEXT SLIDE
From: presentation by @alexbeletsky
HTTP verbs
Represent CRUD on a resource:- GET: read, cachable, retreives a resource- POST: non-cacheable, creates a resource- PUT: updates a resource, safe to call multiple times- DELETE: deletes a resource, safe to call multiple times
Can also use others i.e. PATCH (partial update of a resource)
cornerstone of any REST system standard
RESTful
GET /api/teams
GET /api/teams/1
GET /api/teams/1/players
POST /api/teams
PUT /api/teams/1
DELETE /api/teams/1
now we can see the same API as before, but in a RESTful manner. You can see it's much cleaner, readable and maintainable also much more discoverable
First API GET
public class TeamsController : ApiController{ private readonly IUnitOfWork _uow;
public TeamsController(IUnitOfWork uow){ _uow = uow; }
public IEnumerable Get() { return _uow.Teams; }
public Team Get(int id) { var team = _uow.Teams.FirstOrDefault(i => i.Id == id); if (team == null) throw new HttpResponseException(HttpStatusCode.NotFound); return team; }
First API POST
public void Post(Team value) { if (!ModelState.IsValid) throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState));
_uow.Teams.Add(value); _uow.SaveChanges(); }
First API PUT
public void Put(int id, Team value) { if (!ModelState.IsValid) throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState));
var team = _uow.Teams.FirstOrDefault(i => i.Id == id); if (team == null) throw new HttpResponseException(HttpStatusCode.NotFound);
team.League = value.League; team.Name = value.Name;
_uow.SaveChanges(); }
First API DELETE
public void Delete(int id) { var team = _uow.Teams.FirstOrDefault(i => i.Id == id); if (team == null) throw new HttpResponseException(HttpStatusCode.NotFound);
_uow.Teams.Remove(team); _uow.SaveChanges();
} }
Demo: first API
Content negotiation
Dynamically deciding the media type
Same data can be represented in various formats:- JSON XML CSV binary anything to what your data can be serialized/deserialized from
In Web API done with MediaTypeFormatters
content negotiation is a two-way process, it can determine the format (media type) of a response based on the request it can also determine how to deserialize the incoming request there are countless examples of media types, two most popular ones are XML & JSON media type don't have to support read and write for example RSS is read only
Content negotiation in Web API
Web API uses the following precedence:1. MediaTypeMapping/api/resource.json, /api/resource?format=json
2. Accept headersAccept: application/json
3. Content type headerContent-Type: text/xml
4. MediaTypeFormatter order & check whether a formatter can serialize/deserialize a given type
media type mappings allow you define extension i.e. .json or querystring paramter i.e. ?format=json accept headers are sent by default by i.e. The browser 'text/html' content-type headers come in play when client sens in some data, for example on POST or PUT. If there is data coming back, it wil be symmetrically formatted finally the mediatypeformatter order and JSON is default. Web API will also check if the given Type is supported by the formatter. Like we said, RSS is write only and FormData read only
So how my model gets serialized?
Out of the box supports:- XML (DataContractSerializer / XmlSerializer)- JSON (DataContractSerializer / JSON.NET)- Form values (from client only, one-way)
out of the box web API has 3 formatters, but form is read only XML & JSON are universal
And how my model gets deserialized?
Simple paramters can be read from URI querystring & route data - through model binding
Complex types come from request body and use MediaTypeFormatters
Body can only be read once (forward-only stream), unless buffered
when it comes to reading data is a bit more compllicated since data can also come from URI QS and route data this type of data is read using model binders not media type formatters formatters only scan the body, normally for complex types (eve though primitives can also be sent) body in Web API can only be read once, that's for performance reasons. in MVC the whole body was buffered into memoery. Now imagine a request that has an body of 400MB of upload data can cause server instability
Extending content negotiation
Very easy, some examples:- BSON (binary JSON)- ServiceStack.Text (instead of JSON.NET)- MessagePack- Mobi (returning ebook!)- RSS/Atom- Supporting Razor views (text/html)
web api formatter collection can be super easily extended
the whole point is to abstract away the request/response format from the actual action which should work with CLR types
Web API processing pipeline
By Kiran Challa, MS
what's important here are the colors. message handlers run before anything else, they process raw request and are perfect for things like API usage logging or authentication handlers can run on specific routes only if needed think public/prvate API filters run before controller actions then the action runs and the process reverses so whatever ran first, runs last
All in all this is called the russion doll model
So maybe we dont need the chart
Message Handlers
Russian doll model
run first and last
process raw HttpRequestMessage & HttpResponseMessage
Ideal for generic tasks such as authentication or API usage logging
Can be global or route-specific
mesage handlers dont exist in MVC suitable for generic tasks applicable for entire or part of your API filters do the same except they apply to individual action architecturaly, handlers are singletons so it creates additional considerations when it comes to DI and so on
Client-server symmetry
By: Henrik Frystyk Nielsen
Message handlers can run on server and on the client
HttpServer is a message handler itself
Filters
Conceptually same as in MVC
Cached for performance (unlike MVC)
Pre-action processing of raw HttpRequestMesage
Post-action processing of raw HttpResponseMessage
filters allow you do to pre/post processing perfect for applying repeated logic such as checking model state or checking the incoming request for null values you can have many filters
Controllers
Represent your API resources
Similar as in MVC
Routing engine determines which controller to use
Supports nested resources
Dispatching actions
By default HTTP verb based (RESTful)
Actions matched: by prefix (i.e. GetAll, GetById) or
by action attribute (i.e. [HttpPost])
Can be changed to action based (RPC style)
the default dispatched is RESTful your actions don't have to be named as HTTP verbs, but should be prefixed by the HTTP verb alternatively you can use the attribute
How extendible is Web API?
Almost everything in the framework is interface based, and as a result easily replaceable:- content negotiation- model binding- dependency injection- tracing- pretty much any other service
in the original ASP.NET web forms nothing was extendible
it then started changning, later versions were much better
the big strength about Web API is that you can replace almost everything in the framework entire content negotiation engine (remember the slide where i showed the order of precendece) this entire logic can be scraped. model binding can be customized, and changed to i.e. MVC style binding if you want you can plug in any DI container you can plug in any logging framework, even for the internal tracing
Anything else?
TDD, BDD whole pipeline can run in memory
Async from top-to-bottom scales well
Simple: figure out your resources, and build around them
Next release (Feb 2013) will have OData support
Integrates with SignalR
because of memoery hosting, Web API facilitates very well TDD, BDD asynchrony is very important as it increases your overall thgroughput beauty in simplicity Odata is MS data exchange protocol. I.e. Netflix API supports it and it's great for querying data works well with signalr for realtime apps, so you can have an app which i.e. Adds an order through POST and immediately notifies the connected clients about the new order
Demo: first API self hosted
Demo: first API memory hosted
Demo: adding BSON formatter
Demo: P2P in WPF
Follow these guys
@frystyk@glennblock@tourismgeek@darrel_miller@aliostad@benfosterdev@pwalat@pmhsfelix
@filip_woj