HTTP Message Handler in Web API: Implement Server-Side Message Handler

We are in the kingdom of HTTP protocols that have ruled the web for many years. It’s pretty old; it's simple and stateless in nature. The key concept of the HTTP protocol is Request and Response.

The client makes a request for some resource to a HTTP server and the server takes it, processes it and prepares a response message to the client that got the request and finally the “server HTTP forgets about the request and response”.

This is the key concept of a stateless service.

Anyway, we are not much interested in explaining the nature of the HTTP protocol; rather we will learn how a request message passes from one block to another block to a HTTP server. In the broad scenes we can call the block as a “Message Handler”. In this article we will understand the concept of Message Handler and we will create our own Message Handler to do specific task.

What a Message Handler is

A Message Handler is a class that receives a HTTP request and returns a HTTP response. The base class of a Message Handler is HttpMessageHandler. That description is a little formal, let’s try to understand it in our own words.
Message Handlers are nothing but a chain of classes (it may be system defined or defined by us) that sits next to the process of HTTP request and response through a pipeline.

HTTP Message handler

For example, one HTTP request has come to a HTTP server, now the request will be passed to HandlerA and after processing it in HandlerA , it might go to HandlerB and so on. Now, the advantage here is that we can perform specific tasks within each handler depending on our business needs.

Ok, so the key concept is, Message Handlers are a set of classes (called delegate handlers) that process HTTP requests and responses to perform some operation in the HTTP request and response.

The question may occur to you whether the message handle concept is present only in a HTTP server? No, it is also available in the client-side. Very shortly we will discuss both of them.

Server- side Message Handlers

On the Server side, the Web API pipeline uses some built-in Message Handlers. The term “built-in” implies that those handlers are already set up by the MVC Web API framework. Those are:

  • HttpServer: This handler collects requests from the host.
  • HttpRoutingDispatcher: It dispatches the request based on the route after fetching routing information from a routing table.
  • HttpControllerDispatcher: sends the request to a Web API controller.

So, those are the server-side pre-defined Message Handlers that have provide smooth message (read HTTP request and response) passing in Web API applications (In the server side). There are two questions that may arise in this context.

Where can we define our own Message Handler? And what is the necessity to do it? Let’s try to answer both one by one.

We can inject our own message handling mechanism within those pre-defined Message Handlers, in other words we can add a custom Message Handler within a handler chain. (We will see that in code.)

The next question is, “Why do we need to implement our own Message Handler?”. People like customization. There might be a situation where we need to perform our custom logic in a HTTP request and response. Here are some situations where we can implement logic in a custom Message Handler:

  • In a server we want to log each and every HTTP request from multiple locations across the world.
  • We want to monitor each request and protocol version and type. For example if the communication protocol does not use HTTPS then drop the request.
  • If we want to perform custom verification and validation logic on each and every request.
  • To implement a PRG Pattern (that we will discuss on another day).

Ok, so those are the possible and common situations where a custom Message Handler is useful. If we show the use of a custom handler in a picture then it will look like this:

HTTP Message handler in Web API

Fine, let’s implement one server-side custom Message Handler and let's observe the execution.

To write a custom Message Handler, we need to define our own class that will be derived from the DelegatingHandler class. Here is a sample example.

  1. public class MessageHandler1 : DelegatingHandler  
  2. {  
  3. }

Now we need to override the SendAsync() function within this class. as in the following.

  1. public class MessageHandler1 : DelegatingHandler  
  2. {  
  3.     protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)  
  4.     {  
  5.     }  
  6. }

So, we have defined our own Message Handler class, now we need to do some operation within it.

Return each HTTP request from custom handler

Let’s think that for some reason we will take down our HTTP server. For some reason, let’s think about it; we will accept all the client's requests but rather than navigating to those requests to an appropriate action we will generate a response message from a Message Handler and we will return it to the client. Let’s try to implement that.

Step 1: Here is our controller and action that we will call by HTTP request

  1. using System.Net.Http;  
  2. using System.Web;  
  3. using TestWEB_API.Models;  
  4. using System.Web.SessionState;  
  5. using System.Web.Http;  
  6. using System.Web.Mvc;  
  7. namespace TestWEB_API.Controllers  
  8. {  
  9.     public class ValuesController : ApiController  
  10.     {  
  11.         public string[] Get()  
  12.         {  
  13.            return new string[] {"Sourav","Kayal" };  
  14.         }  
  15.      }  
  16. } 

It’s a simple one, when we will call the Get() action it will return a set of strings.

Step 2: Define our own Message Handler in the Global.asax page.
 

  1. public class MessageHandler1 : DelegatingHandler  
  2. {  
  3.     protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)  
  4.     {  
  5.         var response = new HttpResponseMessage(HttpStatusCode.OK)  
  6.     {  
  7.     Content = new StringContent("We got your request but did not process it !!")  
  8.     };  
  9.         var tsc = new TaskCompletionSource<HttpResponseMessage>();  
  10.         tsc.SetResult(response);  
  11.         return await tsc.Task;  
  12.     }  
  13. }

As in our previous explanation, we have declared the MessageHandler1 class derived from DelegatingHandler and within that we have overriden the SendAsync() function.

Within this function we are configuring our own response message with the status code 200 (OK) and in the next step we are returning this response message to the client. So the overall operation is as in the following.

When a HTTP request arrives MessageHandler1 will execute and it will return one HTTP message on its own, without processing the HTTP request further. So ultimately we are preventing each and every HTTP request from reach it’s higher level.

Step 3: Register the Message Handler.

This is the last step where we will register the Message Handler class. Add the following lines in the Application_start() of the Global.asax page.

  1. protected void Application_Start()  
  2. {  
  3.     WebApiConfig.Register(GlobalConfiguration.Configuration);  
  4.     GlobalConfiguration.Configuration.MessageHandlers.Add(new MessageHandler1());  
  5. } 

Here we are registering MessageHandler1() in the message handling pipeline.

Step 4: Run the application and invoke the Get() action.

We are in the last step of the example. Now it’s time to access the Get() request in the browser. Here we are doing the same.

Get action

And we are experiencing the message that we have set in our custom Message Handler. So the HTTP message is not reaching the Get() action and before that it’s returning to our MessageHandler1 class.

Cool, we have successfully implemented our first custom Message Handler. The beginning of this article explained that we can implement a chain of Message Handlers. Yes, we can implement more than one custom message handle.

Implement Message Handler chain

It’s a common situation in applications where more than one Message Handler is needed. So, in that situation we can chain more than one handler as in the following.

  1. public class MessageHandler1 : DelegatingHandler  
  2. {  
  3.     protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)  
  4.     {  
  5.          Debug.WriteLine("Process request handler 1 begin");  
  6.          // Call the inner handler.  
  7.          var response = await base.SendAsync(request, cancellationToken);  
  8.          Debug.WriteLine("Process response handler 1 end");  
  9.           return response;  
  10.        }  
  11. }  
  12. public class MessageHandler2 : DelegatingHandler  
  13. {  
  14.     protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)  
  15.     {  
  16.          Debug.WriteLine("Process request handler 2 begin");  
  17.          // Call the inner handler.  
  18.          var response = await base.SendAsync(request, cancellationToken);  
  19.          Debug.WriteLine("Process response handler 2 end");  
  20.          return response;  
  21.     }  
  22. }

Fine, now in which order do they will execute? They will execute depending on their registered order (we can set a proiority, that we will see another day).

If we register those two handlers in the following fashion:

  1. WebApiConfig.Register(GlobalConfiguration.Configuration);  
  2. GlobalConfiguration.Configuration.MessageHandlers.Add(new MessageHandler1());  
  3. GlobalConfiguration.Configuration.MessageHandlers.Add(new MessageHandler2()); 

Then the MessageHandler1() will start to execute at first and then MessageHandler2(). But the response result will be received in reverse order.

The response result will reach MessageHandler2() and then MessageHandler1().

Conclusion

This is the first presentation of Message Handlers in the API article series. We have the idea behind custom Message Handlers and have seen a sample example to implement.

In a future article we will see the execution of a Message Handler and a few more stuff about it.


Similar Articles