ASP.NET Web API–Http Messaging

Posted: March 4, 2012 in ASP.NET
Tags: ,

ASP.NET MVC 4 (right now in Beta) has introduced the ASP.NET Web API , a MVC compliant framework for developing and hosting HTTP services which can be accessed from a variety of clients.In this post we will take how the ASP.NET Web API request processing pipeline works and HTTP request is passed between different processing stages. ASP.NET Web API can be hosted in IIS like a normal ASP.NET Web application and it can be also self hosted within a simple console application.For the sake of simplicity we will use a self hosted application here.

To build such a framework in general we need two main components

  • HTTP Endpoint – A host that can receive HTTP requests and pass it on to a handler or a series of handlers
  • HTTP Handlers – A program that can handle HTTP requests and generate the responses.

The class System.Web.Http.SelfHost.HttpSelfHostServer is a host for the HTTP handlers listening to the incoming requests as shown below:

static void Main(string[] args) 
{ 
            HttpSelfHostConfiguration cfg = new HttpSelfHostConfiguration("http://localhost:7018"); 
            using (HttpSelfHostServer server = new HttpSelfHostServer(cfg)) 
            { 
                 
                server.OpenAsync().Wait(); 
                
                Console.WriteLine("Server Started..."); 
                Console.Read(); 
           }
}

As I am trying to invoke http://localhost:7018 I am getting a HTTP 404 error.

So now the question is who is handling the request and on what basis it is decided that the resource does not exist?. To understand this better we will modify our code using the InnerHandler property of our HttpSelfHostServer.

static void Main(string[] args) 
{ 
    HttpSelfHostConfiguration cfg = new HttpSelfHostConfiguration("http://localhost:7018"); 
    using (HttpSelfHostServer server = new HttpSelfHostServer(cfg)) 
    { 
        
        Console.WriteLine(server.InnerHandler.GetType().FullName); 
        server.OpenAsync().Wait(); 
        
        Console.WriteLine("Server Started..."); 
        Console.Read(); 
    } 
   
} 

The program prints the name of the handler as System.Web.Http.Dispatcher.HttpControllerDispatcher.

This class dispatches an incoming request to a IHttpController implementation. Let’s quickly add a Controller in our code as shown below:

public class CustomersController : ApiController 
    { 
        public IEnumerable<Customer> GetAllCustomers() 
        { 
            return new List<Customer> 
            { 
                new Customer() { Id = 1, Name = "Sankarsan Bose" }, 
                new Customer() { Id = 2, Name = "Sayantan Basu" }, 
            }; 
        }

        public Customer GetCustomerById(int id) 
        { 
            return new Customer() { Id = 1, Name = "Sankarsan Bose" }; 
        } 
    }

We also add the following lines in the server startup code for request routing.

cfg.Routes.MapHttpRoute("API Default", "api/{controller}/{id}"); 
cfg.Routes.MapHttpRoute("API Default1", "api/{controller}/"); 

Now the following requests return data:

http://localhost:7018/api/customers/

http://localhost:7018/api/customers/1

So far, our conclusion is:

a) HttpControllerDispatcher performs the task mapping URL to appropriate Controller e.g. customers maps to CustomersController

b) It also parses the URL and invokes the right method e.g. for GET customers/ it will invoke GetAllCustomers .

To have a little better understanding of how these handlers and messaging internally works we need to take a look into the important classes in System.Net.Http namespace as shown in the diagram below:

 

webapi

Out of these the main key class is  System.Net.Http.HttpMessageHandler. This abstract class represents a HTTP message handler with the following abstract method

  • protected internal abstract Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,CancellationToken cancellationToken) – This method send a HTTP request message as an asynchronous operation.The Task returned by this method represents the asynchronous operation.

Another key class is System.Net.Http.DelegatingHandler as the name suggest this abstract class it represents a base class for all HTTP message handler which delegates the HTTP message processing to another handler.The reference to another System.Net.Http.HttpMessageHandler is maintained using the property InnerHandler.

Now we add one custom message handler in the chain as shown below:

public class CustomHTTPHandler : DelegatingHandler 
{ 
    protected override Task<HttpResponseMessage> SendAsync( 
        HttpRequestMessage request, CancellationToken cancellationToken) 
    { 
        
        return base.SendAsync(request,cancellationToken).ContinueWith<HttpResponseMessage>((t) => 
        { 
            
            HttpResponseMessage response = t.Result; 
            response.Headers.Add("PostProcess", "123456"); 
            return response; 
        }); 
    } 
} 
[/sourcecode ]  

<p>This needs to be added to the server configuration as well:</p>  
1
cfg.MessageHandlers.Add(new CustomHTTPHandler());

This changes the handler chain as shown below:

image

Now the HttpSelfHostServer delegates request to CustomHTTPHandler and CustomHTTPHandler delegates the request to HttpControllerDispatcher.

The custom handler can be used to perform

  • PreProcessing of the request (like validation, manipulation of the header etc.)
  • PostProcessing of the response by using ContinueWith method of the Task object returned by the SendAsync function as shown in the code above. In this code the call to base.SendAsync invokes the SendAsync method of the InnerHandler i.e. HttpControllerDispatcher in this case. The HttpControllerDispatcher routes the requests to CustomersController and response is generated.After that async task completes the code block in ContinueWith is invoked which attaches a new response header.

The response is as shown below:

image

Similarly, we can create a new response in the custom handler and totally break the chain by not forwarding the request to next InnerHandler as shown below:

public class CustomHTTPHandler : DelegatingHandler 
    { 
        protected override Task<HttpResponseMessage> SendAsync( 
            HttpRequestMessage request, CancellationToken cancellationToken) 
        {

            HttpResponseMessage response = new HttpResponseMessage(); 
            response.Content = new StringContent("Hello World"); 
            return Task.Factory.StartNew<HttpResponseMessage>(()=> response); 
        } 
    }

In this post we have considered only one custom handler, there can be multiple such chained together the final one being the HttpControllerDispatcher.

About these ads
Comments
  1. ASP.NET Web API–Http Messaging « Sankarsan’s Journal…

    Thank you for submitting this cool story – Trackback from DotNetShoutout…

  2. Thanks for posting the article, was certainly a great read!

  3. […] ASP.NET Web API & Http Messaging – Sankarsan Bose takes a look at how the various parts of the WebAPI framework architecture come together to for the request processing piepline […]

  4. I have really learned some new things through your blog site.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s