Successfully reported this slideshow.
Your SlideShare is downloading. ×

Nancy + rest mow2012

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Upcoming SlideShare
Spring 4 - A&BP CC
Spring 4 - A&BP CC
Loading in …3
×

Check these out next

1 of 30 Ad

More Related Content

Slideshows for you (20)

Advertisement

Similar to Nancy + rest mow2012 (20)

Advertisement

Recently uploaded (20)

Nancy + rest mow2012

  1. 1. Click to edit Master title style • Click to edit Master text styles – Second level • Third level – Fourth level The Lightweight Approach to » Fifth level Building Web Based APIs with .NET MOW 2012 19-04-2012 1
  2. 2. Agenda  Who Am I?  What is “lightweight”  RestBucks  REST  Nancy
  3. 3. What is lightweight? 3
  4. 4. What is lightweight?  Low ceremony  Low cruft  Conventions 4
  5. 5. What is lightweight?  Open  Agile  Inexpensive 5
  6. 6. Restbucks 6
  7. 7. REST 7
  8. 8. REST – Richardsons Maturity Model Level 3: Hypermedia Level 2: HTTP Verbs Level 1: Resources Level 0: POX-RPC 8
  9. 9. REST - Resources  The basic building blocks of web API  Anything with a URI  http://restbucks.com/menu/  http://restbucks.com/orders/  http://restbucks.com/order/42/  http://restbucks.com/order/42/payment/ 9
  10. 10. REST- Representations GET http://restbucks.com/order/19202048/ HTTP/1.1 Accept: application/vnd.restbucks+xml <?xml version="1.0"?> <order xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="h <links> <link uri="http://restbucks.com/order/19202048" rel="http://restbucks <link uri="http://restbucks.com/order/19202048" rel="http://restbucks <link uri="http://restbucks.com/order/19202048" rel="http://restbucks <link uri="http://restbucks.com/order/19202048/payment" rel="http://r </links> <location>inShop</location> <cost>7.60000</cost> <items> <item> <name>Latte</name> <quantity>1</quantity> <milk>skim</milk> <size>large</size> 10 </item>
  11. 11. REST - Representations GET http://restbucks.com/order/19202048/ HTTP/1.1 Accept: application/vnd.restbucks+json { "Location":inShop, "Cost":7.60000, "Items":[ { "Name":"Latte", "Quantity":1, "Preferences":{ "milk":"skim", "size":"large" } } ], "Status":1, "Links":[ { 11 "Uri":"http://restbucks.com/order/19202048",
  12. 12. REST - verbs  GET  POST  PUT  DELETE  HEAD  OPTIONS  PATCH 12
  13. 13. REST - Headers  Accept  Content-Type  If-None-Match  Etag 13
  14. 14. 14
  15. 15. Why Nancy?  “Close” to http  Very, very readable code  Very explicit routing  Embraces modularity  Embraces IoC/DI  Embraces testing  Runs anywhere 15
  16. 16. Nancy Basics  Organizes your routes public class MainModule : NancyModule { public MainModule() { Get["/"] = _ => "Hello from root"; } } public class SubModule : NancyModule { public SubModule() : base("subpath") { Get["/"] = _ => "Hello from subpath"; } }
  17. 17. Nancy Basics  Defines which verbs you accepts public class MainModule : NancyModule { public MainModule() { Get["/"] = _ => "Hello from root"; Post["/”] = _ => DoPost(Request.Form.my_value) Delete["/{id}”] = p => Delete(p.id); Put["/”] = _ => DoPut(Request.Body); Patch["/”] = _ => DoPatch(Request.Body); } }  HEAD and OPTIONS and automatic
  18. 18. Restbuck on Nancy – Place an Order public OrdersResourceHandler(IRepository<Product> productRepository, IRepository<Order> orderRepository) : base("/orders") { this.productRepository = productRepository; this.orderRepository = orderRepository; Post["/"] = _ => HandlePost(this.Bind<OrderRepresentation>()); } private Response HandlePost(OrderRepresentation orderRepresentation) { var order = TryBuildOrder(orderRepresentation); if (!order.IsValid()) return InvalidOrderResponse(order); orderRepository.MakePersistent(order); return Created(order); } 18
  19. 19. RestBucks on Nancy – View an Order public OrderResourceHandler(IRepository<Order> orderRepository) : base(”/order”) { this.orderRepository = orderRepository; Get["/{orderId}/”] = parameters => GetHandler((int) parameters.orderId); … } public Response GetHandler(int orderId) { var order = orderRepository.GetById(orderId); if (order == null) return HttpStatusCode.NotFound; if (order.Status == OrderStatus.Canceled) return Response.MovedTo(new ResourceLinker(CanceledOrderUri(orderId); if (Request.IsNotModified(order)) return Response.NotModified(); return Response.WithContent(Request.Headers.Accept, OrderRepresentationMapper.Map(order,Request.BaseUri())) .WithCacheHeaders(order); } 19
  20. 20. RestBucks on Nancy – Cancel an Order Delete["/{orderId}/"] = parameters => Cancel((int) parameters.orderId); public Response Cancel(int orderId) { var order = orderRepository.GetById(orderId); if (order == null) return HttpStatusCode.NotFound; order.Cancel("canceled from the rest interface"); return HttpStatusCode.NoContent; } 20
  21. 21. RestBucks on Nancy –Pay an Order Post["/{orderId}/payment"] = parameters => Pay((int) parameters.orderId, this.Bind<PaymentRepresentation>()); public Response Pay(int orderId, PaymentRepresentation paymentArgs) { var order = orderRepository.GetById(orderId); if (order == null) return HttpStatusCode.NotFound; order.Pay(paymentArgs.CardNumber, paymentArgs.CardOwner); return HttpStatusCode.OK; } 21
  22. 22. RestBucks on Nancy – XML or JSON return Response.WithContent(Request.Headers.Accept, OrderRepresentationMapper.Map(order, Request.BaseUri())) .WithCacheHeaders(order); public static Response WithContent<T>(this IResponseFormatter formatter, IEnumerable<Tuple<string, decimal>> acceptHeaders, T content) { var xmlWeight = CalculateWeightForContentType(acceptHeaders, "xml"); var jsonWeight = CalculateWeightForContentType(acceptHeaders, "json"); if (jsonWeight > xmlWeight) return formatter.AsJson(content); else return formatter.AsXml(content); } 22
  23. 23. RestBucks on Nancy – Conditional Gets return Response.WithContent(Request.Headers.Accept, OrderRepresentationMapper.Map(order, Request.BaseUri())) .WithCacheHeaders(order); public static Response WithCacheHeaders(this Response response, IVersionable versionable, TimeSpan? maxAge = null) { return response.WithHeaders( new { Header = "ETag", Value = string.Format(""{0}"", versionable.Version) }, new { Header = "Cache-Control", Value = string.Format("max-age={0}, public", maxAge ?? TimeSpan.FromSeconds(10)) }); } 23
  24. 24. RestBucks on Nancy – Conditional Gets if (Request.IsNotModified(order)) return Response.NotModified(); public static bool IsNotModified(this Request request, IVersionable versionable) { if (!request.Headers.IfNoneMatch.Any()) return false; var etag = request.Headers.IfNoneMatch.First(); return string.Format(""{0}"", versionable.Version) == etag; } public static Response NotModified(this IResponseFormatter formatter, TimeSpan? maxAge = null) { Response response = HttpStatusCode.NotModified; return response.WithHeaders( new { Header = "ReasonPhrase", Value = "Not modified"}, new { Header = "Cache-Control", Value = string.Format("max-age={0}, public", maxAge ?? TimeSpan.FromSeconds(10)) }); } 24
  25. 25. Nancy.Hosting Your Application Nancy Nancy.Hosting …
  26. 26. Nancy.Hosting  Usage:  > Install-Package Nancy.Hosting.*  Hosts:  ASP.NET  WCF  Self  OWIN
  27. 27. Nancy.Testing [Test] public void WhenOrderHasNotChanged_ThenReturn304() { // Arrange var orderRepo = new RepositoryStub<Order>(new Order(1, 123); var app = new Browser( new ConfigurableBootstrapper (with => { with.Dependency<IRepository<Product>>(…); with.Dependency<IRepository<Order>>(orderRepository); } )); // Act var response = app.Get("/order/123/", with => { with.HttpRequest(); with.Header("If-None-Match", ""1""); }); //Assert response.StatusCode.Should().Be.EqualTo(HttpStatusCode.NotModified); 29}
  28. 28. Why Nancy?  “Close” to http  Very, very readable code  Very explicit routing  Embraces modularity  Embraces IoC/DI  Embraces testing  Runs anywhere 30
  29. 29. Why REST + Nancy  Lightweight  Low ceremony  Low cruft  Follows conventions  Open  Agile 31
  30. 30. More …  Restbucks on Nancy: http://github.com/horsdal/Restbucks-on-Nancy  Rest in Practice: http://restinpractice.com/book.html  Nancy: www.nancyfx.org  Me:  Twitter: @chr_horsdal  Blog: horsdal.blogspot.com  email: chg@mjolner.dk 32

Editor's Notes

  • Basics
  • Basics
  • Basics
  • Conneq
  • Brug WhenOrderHasNotChanged_ThenReturn304()

×