Web API Pipeline Revealed: A True Practical Approach

What is WebApi?

This question carries a lot of weight. Web API is a small word but it has lots of extensive features.

Here is an excerpt about Web API:

ASP.NET Web API is a framework that makes it easy to build HTTP services that reach a broad range of clients, including browsers and mobile devices. It is an ideal platform for building RESTful applications on the .NET Framework. This poster shows how an HTTP request flows through the Web API pipeline, and how the HTTP response flows back. The diagram also shows extensibility points, where you can add custom code or even replace the default behavior entirely.

This article is about WebApi and its Pipeline. Pipeline in simple words is HttpRequest as pipeline and HttpResponse as an output. Kindly refer to the image below:

pipeline

This will be an agenda for this article as shown below:

  • WebApi Definition.
  • WebApi Pipeline architecture
  • WebApi Hosting
  • WebApi HttpRequest & HttpResponse Message format
  • WebApi Delegate Handler
  • Routing Dispatcher and per-route message handler
  • HttpControllerDispatcher
  • Authentication & Authorization Filters
  • Model Binders, Value Providers and Action Filters
  • IHttpActionInvoker & Exception Filters
  • Result Conversation

Web API Definition

ASP.NET Web API is a framework that makes it easy to build HTTP services that reach a broad range of clients, including browsers and mobile devices. It is an ideal platform for building RESTful applications on the .NET Framework. This poster shows how an HTTP request flows through the Web API pipeline, and how the HTTP response flows back. The diagram also shows extensibility points, where you can add custom code or even replace the default behavior entirely.

Web API Architecture

Here is typical pipeline architecture for Web API as in the following screenshot:

Architecture

Web API Hosting

You can host Web API inside IIS or inside your own process (self-hosting).

ASP.NET Hosting

You can host Web API on ASP.NET server and IIS server. For more details kindly go through the following details how to host Web API in IIS:  WebApi Hosting in Internet Information Server (IIS 7.5).

Self-Hosting using OWIN

In Self Hosting you can use OWIN to Self-Host ASP.NET Web API, The HttpServer pipeline starts at the HttpSelfHostServer which is an implementation of HttpServer and directly listens to HTTP requests.

WebApi HttpRequest & HttpResponse Message format

The HTTP request message is first converted to an HttpRequestMessage object, which provides strongly typed access to the HTTP message. There are two types of Http messages HttpRequest and HttpResponse. Each of this has their own format before sending it to respective server and received response from server.

The structure of HttpRequestMessage format is as follows with a pictorial representation.

  1. <request-line>  
  2. <general-headers>  
  3. <request-headers>  
  4. <entity-headers>  
  5. <empty-line>  
  6. [<message-body>]  
  7. [<message-trailers>]  
structure

The structure of HttpResponseMessage format is as follows with a pictorial representation.
  1. <Status-line>  
  2. <general-headers>  
  3. <response-headers>  
  4. <entity-headers>  
  5. <empty-line>  
  6. [<message-body>]  
  7. [<message-trailers>]  
structure

This is the way to understand the HttpRequest and HttpResponse messages.

Web API Delegate Handler

HTTP message handlers are the first stage in the processing pipeline after the request leaves the service host. Further it travels in pipeline as HttpRequestMessage in Pipeline. They process HTTP request messages on the way in, and HTTP response messages on the way out. To create a custom message handler, derive from the DelegatingHandler class. You can add multiple message handlers. Message handlers can be global or assigned to a specific route and called as per-route message handler. Per-route message handler is invoked only when the request matches that route. Per-route message handlers are configured in the routing table. A message handler can create the response directly, skipping the rest of the pipeline.

Delegate handlers are extensibility points which you can customize as per your need. One of the reasons may be to verify the request authenticity and to verify some potential information in the http request .You may also customize the Http response as well and customize messages. A message handler can create the response directly, skipping the rest of the pipeline. Kindly refer to the below image for reference to register global handler in pipeline. There is an example, how a message handler might help you,
  • Read or modify request headers.
  • Add a response header to responses.
  • Validate requests before they reach the controller.
code

config.MessageHandlers.Add(new CustomHandler_One());

Routing Dispatcher and per-route message handler 

After registering global handler and its execution request reaches HttpRouteDispatcher and sends it further in pipeline. HttpRoutingDispatcher dispatches the request based on the route. As per the WebApi Pipeline diagram above HttpRouteDispatcher verifies whether Route handler is null or contains any handler and takes an anticipated action on the basis of that. Delegate handlers give you the privilege to customize the pipeline and allow you to skip the pipeline. You can add a message handler to a specific route when you define the route there i s a typical image which describes multiple handlers globally and per route handler in pipeline.

Reference

diagram
Image Source: asp.net

If you notice in above image that MessageHandler2 doesn’t go to the default HttpControllerDispatcher. Here, MessageHandler2 creates the response, on basis of requests that match "PerRoute" never go to a controller further and skips the pipeline. Kindly refer to the code shown below to register the Per-Route handler in WebApiConfig.cs file as shown below in screen shot and code segment as well.

code
  1. public static class WebApiConfig  
  2. {  
  3.     public static void Register(System.Web.Http.HttpConfiguration config)   
  4.   {  
  5.         config.MapHttpAttributeRoutes();  
  6.         config.Routes.MapHttpRoute(name: "DefaultApi", routeTemplate: "api/{controller}/{action}/{id}", defaults: new   
  7.         {  
  8.             id = RouteParameter.Optional  
  9.         });  
  10.         config.MessageHandlers.Add(new CustomHandler_One());  
  11.         config.Routes.MapHttpRoute(name: "PerRoute", routeTemplate: "api2/{controller}/{action}/{id}", defaults: new   
  12.             {  
  13.                 id = RouteParameter.Optional  
  14.             }, constraints: null, handler: new CustomHandler_Two()  
  15.             //handler: HttpClientFactory.CreatePipeline(  
  16.             //new HttpControllerDispatcher(config),  
  17.             //new DelegatingHandler[] { new CustomHandler_Two() })  
  18.         );  
  19.     }  
  20. }  
If you want “PerRoute” handler to execute complete WebApi pipeline as well as further reach to HttpControllerDispatcher then you just require registering PerRoute handler in WebApiConfig as given below in code segment.
  1. public static class WebApiConfig  
  2. {  
  3.     public static void Register(System.Web.Http.HttpConfiguration config)   
  4.   {  
  5.         config.MapHttpAttributeRoutes();  
  6.         config.Routes.MapHttpRoute(name: "DefaultApi", routeTemplate: "api/{controller}/{action}/{id}", defaults: new  
  7.          {  
  8.             id = RouteParameter.Optional  
  9.         });  
  10.         config.MessageHandlers.Add(new CustomHandler_One());  
  11.         config.Routes.MapHttpRoute(name: "PerRoute", routeTemplate: "api2/{controller}/{action}/{id}", defaults: new  
  12.          {  
  13.                 id = RouteParameter.Optional  
  14.             }, constraints: null,  
  15.             // handler: new CustomHandler_Two()  
  16.             handler: HttpClientFactory.CreatePipeline(new HttpControllerDispatcher(config), new DelegatingHandler[]  
  17.             {  
  18.                 new CustomHandler_Two()  
  19.             }));  
  20.     }  
  21. }  
code

HttpControllerDispatcher 

HttpControllerDispatcher sends the request to a Web API controller.

HttpControllerDispatcher is related to Delegate handler somewhere because whenever you create any custom handler it calls SendAsync(request, cancellationToken) method which redirects call to inner Handler and generally this inner handler is HttpControllerDispatcher which handles the controller action request. Kindly refer one of the following screen:

table

This is one of the execution flow of HttpRequest starts from HttpMessageHandler till controller descriptor and Action selector as per my understanding as shown below,
image

Authentication & Authorization Filters

If I think deeply about an above picture than security is an always a major concern in Web-based applications. You should have proper set of implementation in form of Authenticaiton and authorization technique to secure that data. As you know that ASP.Net Web API is a lightweight framework used for building stateless RESTful services that run on HTTP. There is authentication filter introduced in WebApi2. Authentication filters allows you to create an authentication scheme for individual controllers or actions. Both of these works in a pattern like given below:
  • Authentication proves the identity of the client.

  • Authorization determines whether the client can access a particular resource. To implement Authentication filters class should implement System.Web.Http.Filters.IAuthenticationFilter interface.
The IAuthenticationFilter interface has two methods
  • AuthenticateAsync authenticates the request by validating credentials in the request, if present.

  • ChallengeAsync adds an authentication challenge to the HTTP response, if needed.
Here is the flow in the Web API 2 pipeline using Authentication and Authorization filter
  1. Web API creates an authentication filters before invoking an action. Authentication filter can be apply at action scope, controller scope, and global scope.

  2. Web API calls AuthenticateAsync on every filter. Each filter validates credentials in the request. If any filter successfully validates credentials, the filter creates an IPrincipal and attaches it to the request. If an error occurs at filter level than it skips the rest of the WebApi pipeline.

  3. Suppose if there is no error, the HttpRequest goes and execute through the rest of the pipeline.

  4. Finally, Web API calls every authentication filter’s ChallengeAsync method. Filters use this method to add a challenge to the response, if needed. Sometime it happens in response to a 401 error.

  5. The diagram showed below states a possibility and its execution flow. The authentication filter successfully authenticates the HttpRequest, an authorization filter authorizes the request, and the controller action returns 200 (OK). Reference http://asp.net

    flow

Authentication filter has two methods AuthenticateAsync and ChallengeAsync as shown below in code snippet. The primary purpose of the ChallengeAsync is to manage and add challenge in response. There is a class named as ResultWithChallenge below in code segment which is responsible to call ExecuteAsync and further calls InnerResult. ExecuteAsync to create the HTTP response, and then adds the challenge if needed.

  1. public class CustomAuthenticationFilterAttribute: Attribute, IAuthenticationFilter   
  2. {  
  3.   #region IAuthenticationFilter Members  
  4.     public System.Threading.Tasks.Task AuthenticateAsync(HttpAuthenticationContext context, System.Threading.CancellationToken cancellationToken) {  
  5.         return Task.FromResult(0);  
  6.     }  
  7.     public System.Threading.Tasks.Task ChallengeAsync(HttpAuthenticationChallengeContext context, System.Threading.CancellationToken cancellationToken) {  
  8.         context.Result = new CustomResultChallenge(context.Result, "Authentication Failed!!!");  
  9.         return Task.FromResult(0);  
  10.     }  
  11.   #endregion# region IFilter Members  
  12.     public bool AllowMultiple  
  13.     {  
  14.         get   
  15.         {  
  16.             return false;  
  17.         }  
  18.     }#endregion  
  19. }  
Let’s verify that how does WebApi respond from ChallengeAsync with Unauthorized status. Press F5 and see WebApi is running after getting below screen shot:

web api

Send the Get request in order to verify the execution cycle as given below. Copy and paste the following Url (http://localhost:57888/api/employees/GetEmp/5) in PostMan tool as depicted below in screen shot.

output

As soon as you click on the send button it reaches to Custom value provider’s method to execute set of statement and gives you following output in an image shown below:

output

Model Binders, Value Providers

image

Model binding uses the request to create values for the parameters of the action .These values are passed to the action when the action is invoked or binding is a mechanism used by the WebApi to mapping request to an object defined in the controller. Model binding is the process of creating .NET objects using the data sent by the browser in an HTTP request. We have been relying on the model binding process each time defines an action method that takes a parameter. the parameter objects are created by model binding. Model binding is ASP.NET mechanism for mapping HTTP request data directly into action method parameters and custom .Net objects. 
  • For example, when we receive a request for a URL such as "/Home/ Employees/23", the framework must map the details of the request in such a way that it can pass appropriate values or objects as parameters to our action method. A model binder gets raw input values from a value provider and later value provider takes the HTTP request and populates a dictionary of key-value pairs. Further the model binder uses this dictionary to populate the model.

The action invoker, the component that invokes action methods, is responsible for obtaining values for parameters before it can invoke the action method.

Value Providers

Value Providers are the components that feed data to model binders. Feeding the data means installing the data to the Model binder for further use at the action level. Value provider takes the HTTP request and populates a dictionary of key-value pairs which is later used by model binder to populate the model.

The framework contains a few built-in value providers named FormValueProvider, RouteDataValueProvider, QueryStringValueProvider and HttpFileCollectionValueProvider that fetch data from Request.Form, Request.QueryString, Request.Files and RouteData.Values.

The code shown below for CustomValueProvider used at this application level as well as way to use it at action level in an image shown below:

  1. public class CustomHeaderValueProvider: IValueProvider  
  2. {  
  3.   #region IValueProvider Members  
  4.     public Dictionary < stringstring > objCollection;  
  5.     public CustomHeaderValueProvider(HttpActionContext context)   
  6.     {  
  7.         objCollection = new Dictionary < stringstring > ();  
  8.         foreach(var item in context.Request.Headers)   
  9.         {  
  10.             objCollection.Add(item.Key, string.Join(string.Empty, item.Value));  
  11.         }  
  12.     }  
  13.     public bool ContainsPrefix(string prefix)  
  14.     {  
  15.         return objCollection.Keys.Contains(prefix);  
  16.     }  
  17.     public ValueProviderResult GetValue(string key)   
  18.     {  
  19.         string resultValue;  
  20.         if (key == nullthrow new Exception("NullReferenceException");  
  21.         if (objCollection.TryGetValue(key, out resultValue))  
  22.         {  
  23.             return new ValueProviderResult(resultValue, resultValue, System.Globalization.CultureInfo.InvariantCulture);  
  24.         }  
  25.         return null;  
  26.     }#endregion  
  27. }  
  28. public class CustomValueProviderFactory: ValueProviderFactory   
  29. {  
  30.     public override IValueProvider GetValueProvider(HttpActionContext actionContext)  
  31.     {  
  32.         return new CustomHeaderValueProvider(actionContext);  
  33.     }  
  34. }  
code


reminder 

At the time of the model binding the DefaultModelBinder checks with the value providers to determine if they can return a value for the parameter (example empId) by calling the ContainsPrefix method. If none of the value providers registered can return then it checks through CustomtvalueProvider whether such a parameter is stored and if yes it returns the value.

This is one of the best pictorial representations taken from http://asp.net site is shown below which is again self-explanatory.

Image taken from http://asp.net

image

Kindly refer this link for more understanding on Model Binder Invoke Action with Model Binders and Fetch Header Information Using CustomValueProvider in ASP.NET Web API

IHttpActionInvoker & Action Filters

Once ApiControllerActionInvoker selects an action to handle an HTTP request, and is responsible for producing HttpResponse of your action. The action invoker, the component that invokes action methods, is responsible for obtaining values for parameters before it can invoke the action method. In other words, the invoker gets an instance of HttpActionContext and is expected to produce an HttpResponseMessage out of it. For this purpose it has to invoke an ExecuteAsync method on the

HttpActionDescriptor present on the HttpActionContext

Action Invoker can be a point to manage your exception at global level and returns a response on basis of the result returned by action method of controller. There is an interface shown given below to implement custom action invoker which has method to implement as shown below:
  1. public interface IHttpActionInvoker{  
  2. Task<HttpResponseMessage> InvokeActionAsync(HttpActionContext actionContext, CancellationToken cancellationToken);  
  3. }  
There can be three possible scenarios which can be maintained at ActionInvoker level, 
  1. You action returns an object than it has to convert into HttpResponseMessgae by IActionResultConverter and run content negotiation with the help of request.createResponse().

  2. If action returns IHttpActionResult than it can be convert into HttpResponseMessage at action invoker level. Which gives privilege to mold your response at this level?

  3. It can return HttpResponseMessage directly from action method.

I’ve created Custom action invoker at my application level to achieve Exception Handling after returning result by the action and later apply code at action invoker level to change it into HttpResponseMessege.

  1. public class Custom_ControllerActionInvoker: ApiControllerActionInvoker, IHttpActionInvoker  
  2. {  
  3.     public override System.Threading.Tasks.Task < System.Net.Http.HttpResponseMessage > InvokeActionAsync(HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken) {  
  4.         var objResult = base.InvokeActionAsync(actionContext, cancellationToken);  
  5.         actionContext.Request.Properties["RuntimeReturnType"] = objResult.GetType();  
  6.         if (objResult.Exception != null)   
  7.         {  
  8.             Debug.WriteLine("Exception thrwon by controller {0} :", actionContext.ControllerContext.Controller);  
  9.             return Task.Run < HttpResponseMessage > (() => new HttpResponseMessage(HttpStatusCode.InternalServerError));  
  10.         } else if (objResult.Result.StatusCode == HttpStatusCode.Forbidden)   
  11.         {  
  12.             //Log critical error  
  13.             Debug.WriteLine("Exception thrwon by controller {0} :", actionContext.ControllerContext.Controller);  
  14.             return Task.Run < HttpResponseMessage > (() => new HttpResponseMessage(objResult.Result.StatusCode));  
  15.         }  
  16.         return objResult;  
  17.     }  
  18. }  
code

Kindly find a screen shot and code segment to register CustomActionInvoker in an application as shown below:

code
  1. GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpActionInvoker), new Custom_ControllerActionInvoker());  
Action Filters

Custom filters and attributes are an excellent way to inject extra processing logic into the MVC request response pipeline. At some level programmer would be happy to inject some pre-processing or post-processing logic for actions and controllers. In that case we use filters.

This filter will be called before and after the action starts executing and after the action has executed. It comes under namespace using System.Web.Http.Filters;

OnActionExecuting occurs just before the action method is called.

OnActionExecuted occurs after the action method is called, but before the result is executed (before the view is rendered).
  1. public class CustomActionWebApiFilters: ActionFilterAttribute   
  2. {  
  3.     public override void OnActionExecuting(HttpActionContext actionContext)  
  4.     {  
  5.         // pre-processing  
  6.         Debug.WriteLine("Action just added pre-processing logging/information...");  
  7.     }  
  8.     public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)   
  9.     {  
  10.         //Write your custom logic here  
  11.     }  
  12. }  
I’ve also added Exception filter to manage exception at code level an the respective code shown below:
  1. public class CustomExceptionFilterAttribute: ExceptionFilterAttribute  
  2. {  
  3.     public override void OnException(HttpActionExecutedContext actionExecutedContext)   
  4.     {  
  5.         if (actionExecutedContext.Exception is ArgumentException)  
  6.         {  
  7.             actionExecutedContext.Response = new HttpResponseMessage(HttpStatusCode.NotImplemented);  
  8.         }  
  9.     }  
  10. }  
Kindly find a way to register an Exception filter in global.asax file as given below as well as uses at controller’s action level.
  1. GlobalConfiguration.Configuration.Filters.Add(new CustomExceptionFilterAttribute());  
code

reminder

IHttpActionInvoker can be applying to manage Exception at action level.

IHttpActionInvoker can be used to read runtime context sent by action and made further amendment to send it further as HttpResponseMessage.You may learn more about Action filters in WebApi from this link

Result Conversation

As name implies Result conversation is about to convert return value from action in form of HttpResponseMessege.The result returned by the an action can be in multiple form and those forms are given below with pictorial representation taken from

Image taken from http://asp.net

image

 

  • HttpResponseMessege: If return type is HttpResponseMessage sent it directly.

  • Void : If return type is void, create response with status 204 (No Content)

  • IHttpActionResult: Call ExecuteAsync to create an HttpResponseMessage, and then convert to an HTTP response message.

  • Other Types: For return types, Web API uses a media formatter to serialize the return value. Web API writes the serialized value into the response body. The response status code is 200 (OK).
IHttpActionResult plays a vital role in HttpResponseMessege category ,because it allows you return your own return set after introducing in WebAPI2 .There are few advantages of IHttpActionResult are listed below:
  • Moves common logic for creating HTTP responses into separate classes. Which makes code readability easier.

  • Makes the controller action clear and concise, by hiding the low-level details of constructing the response.
IHttpActionResult contains a single method, ExecuteAsync, which asynchronously creates an HttpResponseMessege.
  1. public async System.Threading.Tasks.Task<System.Net.Http.HttpResponseMessage> ExecuteAsync(System.Threading.CancellationToken cancellationToken)  
  2. {  
  3. }  
There is an example of IHttpActionResult which have been used at Authentication Filter level and states that ExecuteAsync just add Header value in response and returns. Please have a quick look at the code shown below.
  1. public class CustomResultChallenge: IHttpActionResult   
  2. {  
  3.   #region IHttpActionResult Members  
  4.     private readonly IHttpActionResult result;  
  5.     private readonly string realm;  
  6.     public CustomResultChallenge(IHttpActionResult result, string realm)   
  7.     {  
  8.         this.result = result;  
  9.         this.realm = realm;  
  10.     }  
  11.     public async System.Threading.Tasks.Task < System.Net.Http.HttpResponseMessage > ExecuteAsync(System.Threading.CancellationToken cancellationToken)   
  12.     {  
  13.         var res = await result.ExecuteAsync(cancellationToken);  
  14.         if (res.StatusCode == HttpStatusCode.Unauthorized)   
  15.         {  
  16.             res.Headers.WwwAuthenticate.Add(new AuthenticationHeaderValue("Basic"this.realm));  
  17.         }  
  18.         return res;  
  19.     }#endregion  
  20. }  
Kindly see vital point marked yellow in the below screen shot;

code

Press F5 and run you WebApi as depicted below in an image,

WebApi
send
Send the Get request in order to verify the execution cycle as given below. Copy and paste the following Url (http://localhost:57888/api/employees/GetEmp/5) in Postman tool as depicted below in screen shot.

wrap

As soon as you click on the send button it reaches to Custom handler one and goes on to next level. Kindly execute the complete HttpMessegePipeline one by one and add your points.

So far we’ve get into each area of WebApi HttpRequest Pipeline and tried to understand few facts happen during its cycle.
  1. Bullet Points. HttpRequest first converts into HttpRequestMessege.

  2. HttpHandler are type of delegate handler and inject to verify the authenticity and to add some preprocessing logic before it goes further in pipeline. Delegate Handler can be creating on per-route basis. If come error/issue occurs at this level can skip the rest of pipeline.

  3. Authentication filters have been introduced in WebApi2.If come error/issue occurs at this level can skip the rest of pipeline.

  4. Mostly classes are derived from using System.Web.Http.

  5. Model Binders and Value Provides plays an important role in parameter binding as well as the added benefit of FormatterParameterBinding.

  6. WebApi2 gives privilege to return IHttpActionResult from action method of controller. Also supports HttpResponseMessege.

  7. You can manage exception at IHttpAcitonInvoker and at ExceptionFilters also.

  8. This is the final structure of an application given below in screen shot.

    solution

Hope you would read all contexts and liked it.

Download the complete project file. 

Disclaimer

This is all my understanding about WebApi; I’d be happy if you run this sample application and get a chance to share your opinion.


Similar Articles