• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Nancy + rest   mow2012
 

Nancy + rest mow2012

on

  • 2,157 views

 

Statistics

Views

Total Views
2,157
Views on SlideShare
1,837
Embed Views
320

Actions

Likes
1
Downloads
18
Comments
0

32 Embeds 320

http://horsdal.blogspot.com 128
http://talk.tretton37.com 39
http://horsdal.blogspot.dk 28
http://www.horsdal-consult.dk 27
http://horsdal.blogspot.com.es 11
http://horsdal.blogspot.ca 9
http://horsdal.blogspot.de 9
http://horsdal.blogspot.co.uk 8
http://horsdal.blogspot.se 8
http://horsdal.blogspot.be 5
http://horsdal.blogspot.com.ar 5
http://horsdal.blogspot.in 4
http://horsdal.blogspot.sg 3
http://horsdal.blogspot.co.nz 3
http://horsdal.blogspot.fi 3
http://somersworth12.aludia.com 3
http://horsdal.blogspot.it 3
http://horsdal.blogspot.no 3
http://horsdal.blogspot.com.br 3
http://www.linkedin.com 2
http://us-w1.rockmelt.com 2
http://horsdal.blogspot.hk 2
http://horsdal.blogspot.ch 2
http://horsdal.blogspot.nl 2
http://www.newsblur.com 1
http://horsdal.blogspot.jp 1
http://horsdal.blogspot.com.au 1
http://horsdal.blogspot.gr 1
http://horsdal.blogspot.fr 1
http://horsdal.blogspot.kr 1
http://horsdal.blogspot.co.at 1
https://www.linkedin.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • Basics
  • Basics
  • Basics
  • Conneq
  • Brug WhenOrderHasNotChanged_ThenReturn304()

Nancy + rest   mow2012 Nancy + rest mow2012 Presentation Transcript

  • 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 201219-04-2012 1
  • Agenda Who Am I? What is “lightweight” RestBucks REST Nancy
  • What is lightweight?3
  • What is lightweight?  Low ceremony  Low cruft  Conventions4
  • What is lightweight?  Open  Agile  Inexpensive5
  • Restbucks6
  • REST7
  • REST – Richardsons Maturity Model Level 3: Hypermedia Level 2: HTTP Verbs Level 1: Resources Level 0: POX-RPC8
  • 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
  • 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>
  • 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",
  • REST - verbs  GET  POST  PUT  DELETE  HEAD  OPTIONS  PATCH12
  • REST - Headers  Accept  Content-Type  If-None-Match  Etag13
  • 14
  • Why Nancy?  “Close” to http  Very, very readable code  Very explicit routing  Embraces modularity  Embraces IoC/DI  Embraces testing  Runs anywhere15
  • 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"; } }
  • 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
  • Restbuck on Nancy – Place an Orderpublic 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
  • RestBucks on Nancy – View an Orderpublic 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
  • 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
  • RestBucks on Nancy –Pay an OrderPost["/{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
  • RestBucks on Nancy – XML or JSONreturn 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
  • 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
  • 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
  • Nancy.Hosting Your Application Nancy Nancy.Hosting …
  • Nancy.Hosting Usage:  > Install-Package Nancy.Hosting.* Hosts:  ASP.NET  WCF  Self  OWIN
  • 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}
  • Why Nancy?  “Close” to http  Very, very readable code  Very explicit routing  Embraces modularity  Embraces IoC/DI  Embraces testing  Runs anywhere30
  • Why REST + Nancy  Lightweight  Low ceremony  Low cruft  Follows conventions  Open  Agile31
  • 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.dk32