2. 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
3. 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
4.
5. 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"/>
6. • The server return an open slot list as
HTTP/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>
7. • The server accept this request and register
name of patient
HTTP/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 be
HTTP/1.1 200 OK [various headers]
<appointmentRequestFailure>
<slot doctor = "mjones" start = "1400" end = "1450"/>
<patient id = "jsmith"/>
<reason>Slot not available</reason>
</appointmentRequestFailure>
9. • 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>
10. • 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
12. • 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>
13. • 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>
14. • 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)
15. Level 3: Hypermedia Controls
• HATEOAS (Hypertext As The Engine Of
Application State)
16. • GET
/doctors/mjones/slots?date=20100104&status=o
pen 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>
17. • POST /slots/1234 HTTP/1.1 [various other
headers]
<appointmentRequest>
<patient id = "jsmith"/>
</appointmentRequest>
18. • 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?
19. 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?
20. 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
21. 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
22. 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
23. Web API service
public 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) {… }
}
24. 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.
25. 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 });
26. 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
27. 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_cod
es
28. Format & model binding
• Media-Type Formatters
// Remove the XML formatter
config.Formatters.Remove(config.Formatters.XmlF
ormatter);
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.DateFormatHandling =
DateFormatHandling.MicrosoftDateFormat;
json.SerializerSettings.Formatting =
Formatting.Indented;
• Content Negotiation
• Model Validation in ASP.NET Web API
29. Dependency Resolver with Autofac
var builder = new ContainerBuilder();
// register autofac modules
builder.RegisterModule<WebModule>();
builder.RegisterModule<DataSurveyModule>();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterFilterProvider();
var container = builder.Build();
DependencyResolver.SetResolver(new
AutofacDependencyResolver(container));