How to get full power from WebApi

21
How to get full power from WebApi Raffaele Rialdi @raffaeler http://iamraf.net

description

WebApi presentation by Raffaele Rialdi at http://webnetconf.eu/ on October 20, 2012 in Milano http://www.iamraf.net @raffaeler

Transcript of How to get full power from WebApi

Page 1: How to get full power from WebApi

How to get full power from WebApi

Raffaele Rialdi@raffaeler

http://iamraf.net

Page 2: How to get full power from WebApi

Thanks to the sponsors

Page 3: How to get full power from WebApi

What is WebApiin one slide

• A library to create HTTP services– HTTP is highly scalable (disconnect, cloud, …)

• Designed to create REST services– WebApi does not automatically imply REST– Use HTTP as an application (not a transport) protocol

• Fits in heterogeneous device/OS scenarios– Avoid typical SOAP versioning problems– It's highly pluggable

• Leverages the Asp.net MVC 4 model

Page 4: How to get full power from WebApi

WebApi is flexible

• oData is a work-in progress– look at nightly builds, avoid current pre-release

• Can be Self-Hosted outside IIS and MVC4– Easy way for inter-AppDomain or inter-Process– Console example:

var config = new HttpSelfHostConfiguration("http://localhost:8000");

config.Routes.MapHttpRoute("API Default", "api/{controller}/{id}",new { id = RouteParameter.Optional });

using (HttpSelfHostServer server = new HttpSelfHostServer(config)){

server.OpenAsync().Wait();Console.WriteLine("Press any key to exit");Console.ReadKey();

}

Page 5: How to get full power from WebApi

THE REQUEST JOURNEY

Page 6: How to get full power from WebApi

Routing to a Controller

• Use the standard MVC Routes– extract Controller, Action and parameters

• Controller selection under the hood– IHttpControllerSelector.SelectController• HttpRequestMessage HttpControllerDescriptor

• Plug-in Controllers using IDependencyResolver– Nuget has a lot of ready to use IoC containers

controllerRequest

Page 7: How to get full power from WebApi

Selecting an Action

• The easiest way is to modify the default Route

• Can use [ActionName("myaction")]– override the method name as the action name

• Can use [NonAction]– exclude a method from being an action

config.Routes.MapHttpRoute(name: "DefaultApi",routeTemplate: "api/{controller}/{id}",defaults: new { id = RouteParameter.Optional }); config.Routes.MapHttpRoute(

name: "DefaultApi2",routeTemplate: "api/{controller}/{action}/{x}/{y}" );

actioncontrollerRequest

Page 8: How to get full power from WebApi

Selecting an Action by code

• Derive ApiControllerActionSelector– override SelectAction

• Implement IHttpActionSelector– Implement SelectAction– Obtain the previous selector in ctor– Call previous selector

• In SelectAction method:– in: HttpControllerContext– out: HttpActionDescription

actioncontrollerRequest

Use case:Versioning!

Page 9: How to get full power from WebApi

Authorization filter

• [Authorize] is Role oriented• Derive AuthorizeAttribute to go Claim

oriented• [AllowAnonymous] is self-explanatory• Starting from Fx4.5 new universal base classes

– ClaimsPrincipal for every Principal– ClaimsIdentity for every Identity

IPrincipal client = Thread.CurrentPrincipal;

ClaimsPrincipal principal = Thread.CurrentPrincipal as ClaimsPrincipal;ClaimsIdentity identity = principal.Identity as ClaimsIdentity;

authoriz.Request actioncontroller I’ll play withClaims

Page 10: How to get full power from WebApi

Security considerations

• WebApi authorization model is not built-in– AuthorizationFilters / MessageHandlers are used

to plugin the desired mechanism– Per-route handlers gives finer control

• Use Filters/Handlers to add/modify claims

Page 11: How to get full power from WebApi

Model Bind

• IValueProvider (Bind3 example)– useful to populate an action parameter– Require a ValueProviderFactory (applied via attribute)

• HttpParameterBinding (Bind4 example)– Associate a type to a provider

• IActionValueBinder (Bind5 example)– Associate an HttpActionDescription to a provider

• DefaultActionValueBinder (Bind6 example)– Intercept default provider

• IModelBinder (Bind7 example)– Execute the binding. Must provide the value

bindingRequest authoriz.actioncontroller

Page 12: How to get full power from WebApi

Action Filters

• Called before and after the action execution

• Implement IActionFilteror better….

• Derive ActionFilterAttribute– OnActionExecuting– OnActionExecuted

action filter

action filterRequest bindingauthoriz.actioncontrollerRequest bindingauthoriz.actioncontroller

Use case:validation & auditing!

Page 13: How to get full power from WebApi

Target was reached!

• In the action we have different options:– return an entity that will be embedded in a response– build and return the HttpResponseMessage

• Can be an error (no exceptions imply better performances)

or– throw a CLR exception (a filter will convert it in a msg)– throw an HttpResponseException

• returns the HTTP status code of your choice• it's a full response (specify Content, Headers, ReasonPhrase)

action filter

invokeaction

action filterRequest bindingauthoriz.actioncontrollerRequest bindingauthoriz.actioncontroller

Page 14: How to get full power from WebApi

HttpError

• Nice way to create the error message– Errors flow in the same way of the content– Keys/Values can be added for additional infos

var msg = string.Format("Product with id = {0} not found", id);HttpError err = new HttpError(msg);return Request.CreateResponse(HttpStatusCode.NotFound, err);

HTTP/1.1 404 Not FoundContent-Type: application/json; charset=utf-8Date: Thu, 09 Aug 2012 23:27:18 GMTContent-Length: 51

{ "Message": "Product with id = 12 not found" }

var msg = string.Format("Product with id = {0} not found", id);return Request.CreateErrorResponse(HttpStatusCode.NotFound, msg);

Page 15: How to get full power from WebApi

Action filter

• Same filter of the request• OnActionExecuted

action filter

invokeaction

Page 16: How to get full power from WebApi

Exception Filters

• Do not use MVC [HandleError]• Transform CLR exceptions in HTTP messages• Implement IExceptionFilter or better derive

ExceptionFilterAttribute• Mark actions with the attribute

or• Change the global configuration– GlobalConfiguration.Configuration.Filters.Add(new

MyNamespace.NotImplExceptionFilterAttribute());

exceptionfilter

action filter

invokeaction

Page 17: How to get full power from WebApi

Formatting data for the output

• MediaTypeFormatter is the abstract base class to serialize entities in whatever format

• Built-in formatters:– Json.net and Xml formatter are built-in– bson and many others on nuget– your own just deriving this class

• The correct formatter is picked up upon "http content negotiation"

Response formatting exceptionfilter

action filter

invokeaction

Page 18: How to get full power from WebApi

GOING DEEPER

Page 19: How to get full power from WebApi

Message Handlers

• Message Handlers works at the beginning of the pipeline– They can use the message and pass it over– Or can "short-circuit" to the response (early validation)

• MH still don't know the controller, action, etc.• Every endpoint has different MH instances• Typical usage:

– Early validation of the message / headers (security keys)– Packet inspection

RequestRequest HttpControllerDispatcher

HttpRouting

Dispatcher

customMessageHandler

HttpServer ControllerResponse

Page 20: How to get full power from WebApi

Wrap up

• Webapi = extreme pluggability• Just follow the request– Before or later it will become a response

Questions?

Page 21: How to get full power from WebApi

Please rate this sessionScan the code, go online, rate this session