ASP.NET WEB API

31
ASP.NET WEB API @thangchung 08-08-2012

description

 

Transcript of ASP.NET WEB API

ASP.NET WEB API

@thangchung08-08-2012

Agenda

• A model of restful maturity• ASP.NET Web API• Mapping from WCF to Web API• Integrated stack supporting features• What we do in BC Survey project

A model of restful maturity

• Restful coined by Roy Thomas Fielding in his dissesertation (2000)

• A model of restful maturity introduced by Leonard Richardson (2008)

• The glory of REST by Martin Fowler (2010)• We have 4 levels of maturity– Level 0: The swamp of POX (Plain Old XML)– Level 1: Resources– Level 2: HTTP verbs– Level 3: Hypermedia Controls

Level 0: The swamp of POX

• Use RPC (Remote Procedure Invocation)

• POST /appointmentService HTTP/1.1 [various other headers]

<openSlotRequest date = "2010-01-04" doctor = "mjones"/>

• The server return an open slot list asHTTP/1.1 200 OK [various headers]

<openSlotList> <slot start = "1400" end = "1450">

<doctor id = “mjones”/> </slot>

<slot start = "1600" end = "1650"> <doctor id = “mjones”/>

</slot> </openSlotList>

• We choose the the first item and send it to server:POST /appointmentService HTTP/1.1 [various other headers]

<appointmentRequest> <slot doctor = "mjones" start = "1400" end =

"1450"/> <patient id = "jsmith"/>

</appointmentRequest>

• The server accept this request and register name of patientHTTP/1.1 200 OK [various headers]

<appointment> <slot doctor = "mjones" start = "1400" end = "1450"/> <patient id = "jsmith"/> </appointment>

• If some thing wrong, the result should beHTTP/1.1 200 OK [various headers] <appointmentRequestFailure>

<slot doctor = "mjones" start = "1400" end = "1450"/> <patient id = "jsmith"/> <reason>Slot not available</reason>

</appointmentRequestFailure>

Level 1: Resources

• POST /doctors/mjones HTTP/1.1 [various other headers] <openSlotRequest date = "2010-01-04"/>

• HTTP/1.1 200 OK [various headers] <openSlotList> <slot id = "1234" doctor = "mjones" start = "1400"

end = "1450"/> <slot id = "5678" doctor = "mjones" start = "1600"

end = "1650"/> </openSlotList>

• POST /slots/1234 HTTP/1.1 [various other headers] <appointmentRequest>

<patient id = "jsmith"/> </appointmentRequest>

• HTTP/1.1 200 OK [various headers] <appointment> <slot id = "1234" doctor = "mjones" start = "1400"

end = "1450"/> <patient id = "jsmith"/> </appointment>

• The link at the moment should be like this– http://royalhope.nhs.uk/slots/1234/appointment

Level 2: HTTP Verbs

• GET/POST/PUT/DELETE

• Use GET /doctors/mjones/slots?date=20100104&status=open HTTP/1.1 Host: royalhope.nhs.uk

• HTTP/1.1 200 OK [various headers] <openSlotList>

<slot id = "1234" doctor = "mjones" start = "1400" end = "1450"/>

<slot id = "5678" doctor = "mjones" start = "1600" end = "1650"/>

</openSlotList>

• POST /slots/1234 HTTP/1.1 [various other headers] <appointmentRequest>

<patient id = "jsmith"/> </appointmentRequest>

• HTTP/1.1 201 Created Location: slots/1234/appointment [various headers] <appointment>

<slot id = "1234" doctor = "mjones" start = "1400" end = "1450"/>

<patient id = "jsmith"/> </appointment>

• If something wrong when we use POST to server, the result should be HTTP/1.1 409 Conflict [various headers] <openSlotList>

<slot id = "5678" doctor = "mjones" start = "1600" end = "1650"/>

</openSlotList>• Benefits: – Caching on GET request (natural capability with

HTTP protocol)

Level 3: Hypermedia Controls

• HATEOAS (Hypertext As The Engine Of Application State)

• GET /doctors/mjones/slots?date=20100104&status=open HTTP/1.1 Host: royalhope.nhs.uk

• HTTP/1.1 200 OK [various headers] <openSlotList> <slot id = "1234" doctor = "mjones" start = "1400" end = "1450"> <link rel = "/linkrels/slot/book" uri = "/slots/1234"/> </slot> <slot id = "5678" doctor = "mjones" start = "1600" end = "1650"> <link rel = "/linkrels/slot/book" uri = "/slots/5678"/> </slot>

</openSlotList>

• POST /slots/1234 HTTP/1.1 [various other headers] <appointmentRequest>

<patient id = "jsmith"/> </appointmentRequest>

• HTTP/1.1 201 Created Location: http://royalhope.nhs.uk/slots/1234/appointment [various headers]

<appointment> <slot id = "1234" doctor = "mjones" start = "1400" end = "1450"/>

<patient id = "jsmith"/> <link rel = "/linkrels/appointment/cancel" uri =

"/slots/1234/appointment"/> <link rel = "/linkrels/appointment/addTest" uri =

"/slots/1234/appointment/tests"/> <link rel = "self" uri = "/slots/1234/appointment"/> <link rel = "/linkrels/appointment/changeTime" uri =

"/doctors/mjones/slots?date=20100104@status=open"/> <link rel = "/linkrels/appointment/updateContactInfo" uri = "/patients/jsmith/contactInfo"/>

<link rel = "/linkrels/help" uri = "/help/appointment"/> </appointment>

• What’s benefit of those?

ASP.NET Web API

• What is the purpose of the WebAPIs?• Why do we need REST HTTP services? What’s

wrong with SOAP-over-HTTP?• Why did the WebAPIs move from WCF to

ASP.NET MVC?• Is there still a use for WCF? When should I

choose Web APIs over WCF?

Mapping from WCF to Web API

• WCF Web AP -> ASP.NET Web API• Service -> Web API controller• Operation -> Action• Service contract -> Not applicable• Endpoint -> Not applicable• URI templates -> ASP.NET Routing• Message handlers -> Same• Formatters -> Same• Operation handlers -> Filters, model binders

Integrated stack supporting features

• Modern HTTP programming model• Full support for ASP.NET Routing• Content negotiation and custom formatters• Model binding and validation• Filters• Query composition• Easy to unit test• Improved Inversion of Control (IoC) via DependencyResolver• Code-based configuration• Self-host

What we do in BC Survey project

• Introduced Web API service• Web API routing and actions• Working with HTTP (Verb & return status)• Format & model binding• Dependency Resolver with Autofac• Web API clients• Host ASP.NET Web API on IIS

Web API servicepublic class SurveyAPIController : BaseApiController{ // GET api/Survey [Queryable] public IQueryable<SurveyDTO> Get() { return _surveyAppService.GetAllSurvey().AsQueryable(); } // GET api/Survey/5 public SurveyDTO Get(int id) { … } // POST api/Survey public HttpResponseMessage Post(SurveyDTO value) { … } // PUT api/Survey/5 public HttpResponseMessage Put(int id, SurveyDTO value) { … } // DELETE api/Survey/5

public HttpResponseMessage Delete(int id) {… }}

Web API service

• OData (Open data protocol): The Open Data Protocol is an open web protocol for querying and updating data. The protocol allows for a consumer to query a datasource over the HTTP protocol and get the result back in formats like Atom, JSON or plain XML, including pagination, ordering or filtering of the data.

Web API routing and actions

• routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}", new { id = RouteParameter.Optional });

MapHttpRoute really different from default routing in ASP.NET MVC• routes.MapRoute("Default",

"{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });

Working with HTTP (Verb & return status)

• It have 9 method definitions like– GET– HEAD– POST– PUT– DELETE– TRACE– CONNECT

• We can reference more at http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

Working with HTTP (Verb & return status)

• 200 OK• 201 Created• 400 Bad Request• 401 Unauthorized• 404 Not Found• 409 Conflict• 500 Internal Server Error• 501 Not Implemented• Reference more at

http://en.wikipedia.org/wiki/List_of_HTTP_status_codes

Format & model binding

• Media-Type Formatters// Remove the XML formatter

config.Formatters.Remove(config.Formatters.XmlFormatter);

var json = config.Formatters.JsonFormatter;json.SerializerSettings.DateFormatHandling =

DateFormatHandling.MicrosoftDateFormat;json.SerializerSettings.Formatting =

Formatting.Indented; • Content Negotiation• Model Validation in ASP.NET Web API

Dependency Resolver with Autofac

var builder = new ContainerBuilder(); // register autofac modulesbuilder.RegisterModule<WebModule>();builder.RegisterModule<DataSurveyModule>();builder.RegisterControllers(Assembly.GetExecutingAssembly());builder.RegisterApiControllers(Assembly.GetExecutingAssembly());builder.RegisterFilterProvider();

var container = builder.Build();DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

Q & A