Embrace HTTP with ASP.NET Web API

  • Upload
    filip-w

  • View
    5.900

  • Download
    5

Embed Size (px)

Citation preview

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