REST &.NET James Crisp.NET Practice Lead ThoughtWorks Australia
James Crisp
The Web
*-ilities
Scalability
Recoverability & Reliability
Security
Discoverability
How to bring to Web services?
Tunneling RPC URLs POX SOAP & WS-*
REpresentational State Transfer
REST contributes... the rationale behind the modern Web's software architecture Roy Fielding
Resources e.g. Person, Car, Post
Representations Bill Gates m
Addressability
Uniform Interface
GET POST HEAD PUT DELETE OPTIONS Support
GET GET /people/joe_citizen HTTP/1.1 Host: mysite.com Accept: application/xml
Response 200 OK Content-Type: application/xml Last-Modified: :00.. Joe Citizen 42 m
HEAD HEAD /people/joe_citizen HTTP/1.1 Host: mysite.com 200 OK Content-Type: application/xml Last-Modified: :00.. ETag: a32daf15-b33da2a4d Response
POST POST /people HTTP/1.1 Content-Type: text/xml Host: mysite.com.... Tina Jones 25 F
Response 201 CREATED Location: /people/tina_jones (optionally with body)
PUT PUT /people/tina_jones HTTP/1.1 Content-Type: text/xml Host: mysite.com.... Tina Jones 24 F
Response 200 OK Location: /people/tina_jones (optionally with body)
DELETE DELETE /people/joe_citizen HTTP/1.1 Host: mysite.com 200 OK Content-Type: application/xml joe_citizen Response
OPTIONS OPTIONS /people HTTP/1.1 Host: mysite.com 200 OK Allowed: GET,HEAD,POST Response
Status Codes
2xx = All good 200 – OK 201 – Created
3xx = Redirect 301 – Moved permanently 307 – Temporary redirect 304 – Not modified (ie, see cache)
4xx = Client error 400 – Bad request 401 – Unauthorized 403 – Forbidden 405 – Method not allowed 409 – Conflict
5xx = Server error 500 – Internal server error
Headers
Content-Type: text/html application/xml image/jpeg....
WWW-Authenticate: Authorization:
Last-Modified: If-Modified-Since: ETag: If-None-Match:
Location:
Describe your services?
URI Templates
Start URL + Links Tina Jones <link rel="history" href="/tjones/account_history"> <link rel="close" verb="delete" href="/tjones">
Microformats Tina Jones <link rel="transaction-search" href="account_history? from={date-from}& to={date-to}">
State Management Search google.com/ search?q=rest google.com/search?q=rest& start=10 Next Page Searching Searched More Results
Data Format?
XHTML Accounts <a rel="account_details" href="/tjones">Tina Jones.....
JSON { "account_name": "Tina Jones", "links": {"history": "/tjones/history"} }
Framework
Ordering Pizza
GET / HTTP/1.1 Host: epizza.com Content-Type: application/xml
Response 200 OK Location: Content-Type: application/xml Content-Length:... Welcome! <link rel="place-order" href="/orders" />
Let's see the menu! GET /menu HTTP/1.1 Host: epizza.com Content-Type: application/xml
200 OK Location: <link rel="place-order" href="/orders" /> Menu Response
Ordering time! POST /orders HTTP/1.1 Host: epizza.com Content-Type: application/xml Content-Length:...
201 Created Location: Content-Type:... <link rel="destination" href="/orders/413/address"> Place Order Response
Beer with that?
OPTIONS /orders/413 HTTP/1.1 Host: epizza.com 200 OK Allowed: GET, HEAD, POST, PUT
Add Beer POST /orders/413 HTTP/1.1 Host: epizza.com Content-Type: application/xml Content-Length:...
200 OK Location: Content-Type:... <link rel="destination" href="/orders/413/destination"> Response
Destination Address PUT /orders/413/address HTTP/1.1 Host: epizza.com Content-Type: application/xml Content-Length: Rue Rd Potts Point
Destination Response 200 OK Host: epizza.com Content-Type: application/xml Content-Length: Rue Rd Potts Point
200 OK Location: Content-Type:... GET /orders/413
Can we? OPTIONS /orders/413 HTTP/1.1 Host: epizza.com 200 OK Allowed: GET, HEAD
Too late!
Back at the ePizza Kitchen..
GET /orders
Implementation
Client var request = (HttpWebRequest) WebRequest.Create(URL); request.Method request.ContentType request.GetRequestStream() var response = (HttpWebResponse)request.GetResponse(); response.StatusCode response.Headers response.GetResponseStream()
Server
IHttpHandler public class RestHandler : IHttpHandler { public void ProcessRequest(HttpContext context) { context.Response.ContentType = "application/xml"; if (context.Request.HttpMethod == "GET") { context.Response.Write("... "); }
WCF REST [ServiceContract] public interface IPizzaService { [WebGet(UriTemplate="/orders/{orderId}")] [OperationContract] Order GetOrder(int orderId); }
Status codes? Headers? Links? Microformats?
ASP.NET MVC
Routing Table Controller Method ModelView
Routes In GlobalApplication : HttpApplication void RegisterRoutes(RouteCollection routes) { routes.MapRoute( "AddToOrder", "orders/{id}", new { controller = "Orders", action = "AddToOrder" }, new { httpMethod = new HttpMethodConstraint("POST")});... }
Controller public class OrdersController : Controller { public ActionResult AddToOrder(int id) { var order = Order.Load(id); var itemToAdd = CreateMenuItemFromRequest(); order.Items.Add(itemToAdd); order.Save(); // response.StatusCode = 200; return View(order); }
Model public class Order { public MenuItem[] Items { get {... }; } public Address DeliveryAddress { get; set; } }
View " /> <link rel="destination" href=...
MVC REST Wrinkles
See also... Slides & Code MVC RESTful Web Services
- web - bridge - web - defibrillator - padlocks - ws* stack - tunnel - fielding - bill gates - network plugs - speedometers - Petco explosion - letter - Eiffel tower - pizza restaurant - pepperoni pizza - corona - salad pizza boxes – REST book Image References
Questions?