The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
Nancy + rest mow2012
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. Agenda
Who Am I?
What is “lightweight”
RestBucks
REST
Nancy
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
15. Why Nancy?
“Close” to http
Very, very readable code
Very explicit routing
Embraces modularity
Embraces IoC/DI
Embraces testing
Runs anywhere
15
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. 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. 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. 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. 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. 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. 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. 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. 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. Nancy.Hosting
Your Application
Nancy
Nancy.Hosting
…