KEMBAR78
How to get full power from WebApi | PPTX
How to get full power from
         WebApi
        Raffaele Rialdi
          @raffaeler
       http://iamraf.net
Thanks to the sponsors
What is WebApi
                  in 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
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();
            }
THE REQUEST JOURNEY
Routing to a Controller
Request      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
Selecting an Action
Request      controller      action


   • The easiest way is to modify the default Route
    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}" );

   • Can use [ActionName("myaction")]
          – override the method name as the action name
   • Can use [NonAction]
          – exclude a method from being an action
Selecting an Action by code
Request      controller   action


   • Derive ApiControllerActionSelector            Use case:
          – override SelectAction                  Versioning!


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

   • In SelectAction method:
          – in: HttpControllerContext
          – out: HttpActionDescription
Authorization filter
Request         controller        action         authoriz.                           I’ll play with
                                                                                          Claims

   •      [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;
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
Model Bind
Request      controller   action      authoriz.   binding



   • 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
Action Filters
                                                         action
Request      controller   action   authoriz.   binding    filter



   • Called before and after the action execution

                                                               Use case:
   • Implement IActionFilter                                   validation &
                                                               auditing!
          or better….
   • Derive ActionFilterAttribute
          – OnActionExecuting
          – OnActionExecuted
Target was reached!
                                                             action     invoke
Request      controller    action   authoriz.    binding      filter    action



   • 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)
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);

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


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

 { "Message": "Product with id = 12 not found" }
Action filter
                                 action    invoke
                                  filter   action



• Same filter of the request
• OnActionExecuted
Exception Filters
                                 exception   action     invoke
                                   filter     filter    action



• 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());
Formatting data for the output
                                      exception   action    invoke
              Response   formatting                         action
                                        filter     filter



• 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"
GOING DEEPER
Message Handlers
  Request                custom       Http         Http
            HttpServer   Message    Routing     Controller   Controller
 Response                Handler   Dispatcher   Dispatcher



• 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
Wrap up
• Webapi = extreme pluggability
• Just follow the request
  – Before or later it will become a response 



            Questions?
Please rate this session
Scan the code, go online, rate this session

How to get full power from WebApi

  • 1.
    How to getfull power from WebApi Raffaele Rialdi @raffaeler http://iamraf.net
  • 2.
    Thanks to thesponsors
  • 3.
    What is WebApi in 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
  • 4.
    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(); }
  • 5.
  • 6.
    Routing to aController Request 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
  • 7.
    Selecting an Action Request controller action • The easiest way is to modify the default Route 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}" ); • Can use [ActionName("myaction")] – override the method name as the action name • Can use [NonAction] – exclude a method from being an action
  • 8.
    Selecting an Actionby code Request controller action • Derive ApiControllerActionSelector Use case: – override SelectAction Versioning! • Implement IHttpActionSelector – Implement SelectAction – Obtain the previous selector in ctor – Call previous selector • In SelectAction method: – in: HttpControllerContext – out: HttpActionDescription
  • 9.
    Authorization filter Request controller action authoriz. I’ll play with Claims • [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;
  • 10.
    Security considerations • WebApiauthorization 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
  • 11.
    Model Bind Request controller action authoriz. binding • 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
  • 12.
    Action Filters action Request controller action authoriz. binding filter • Called before and after the action execution Use case: • Implement IActionFilter validation & auditing! or better…. • Derive ActionFilterAttribute – OnActionExecuting – OnActionExecuted
  • 13.
    Target was reached! action invoke Request controller action authoriz. binding filter action • 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)
  • 14.
    HttpError • Nice wayto 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); var msg = string.Format("Product with id = {0} not found", id); return Request.CreateErrorResponse(HttpStatusCode.NotFound, msg); HTTP/1.1 404 Not Found Content-Type: application/json; charset=utf-8 Date: Thu, 09 Aug 2012 23:27:18 GMT Content-Length: 51 { "Message": "Product with id = 12 not found" }
  • 15.
    Action filter action invoke filter action • Same filter of the request • OnActionExecuted
  • 16.
    Exception Filters exception action invoke filter filter action • 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());
  • 17.
    Formatting data forthe output exception action invoke Response formatting action filter filter • 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"
  • 18.
  • 19.
    Message Handlers Request custom Http Http HttpServer Message Routing Controller Controller Response Handler Dispatcher Dispatcher • 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
  • 20.
    Wrap up • Webapi= extreme pluggability • Just follow the request – Before or later it will become a response  Questions?
  • 21.
    Please rate thissession Scan the code, go online, rate this session

Editor's Notes