CHAPTER 8
We mentioned message handlers in Chapter 3 when we saw how a request is processed. Now we go a little deeper to understand how they are implemented and how they add functionality to our application.
The typical behavior of a message handler is to obtain the request, make some operation on the request, and then pass it to the next handler in the chain.
A message handler is simply a class that inherits the HttpMessageHandler abstract class. The interface of this class, if we take away the IDisposable interface, is only one method that receives the HttpRequestMessage and returns an HttpResponseMessage.
In fact, the aim of a message handler is simply to receive a request message (HttpRequestMessage) and return a response (HttpResponseMessage). The ASP.NET Web API composes these handlers in a chain where every handler is a reference to the next (through the InnerHandler property) so that a handler can execute the call and pass the result to the next. The final result is like an onion that is being traversed by the request and response messages.
HttpResponseMessage |
HttpRequestMessage |
Message handlers can be used in several ways. For example, we could build a message handler that adds a custom header to the response. The code is very simple and reflects the simplicity in the architecture:
The previous code demonstrates how to create a handler that simply adds a new entry in the request header (X-My-custom-Header) and passes the call to the base class for further processing.
We are inheriting from the DelegatingHandler class that has already implemented the mechanism to manage the passing calls to the other handlers in the chain. DelegatingHandler itself derives from HttpMessageHandler.
Handlers could also be used to log the requests or the errors:
In this case, we pass the call to the base class for execution since we need to know if the call was successful or an error was thrown. We get the response and write to the log in case of an error.
Once defined, a handler needs to be added to the configuration so that the ASP.NET Web API can use it in the execution pipeline:
// in WebApiConfig.cs config.MessageHandlers.Add(new CustomHeaderMessageHandler()); config.MessageHandlers.Add(new LogMessageHandler()); |
We must consider that the order in which we register the handler is important, since it is executed in a top-down fashion. That is, the first entry is invoked first for a request message but last for a response message (as explained in the previous illustration).
Message handlers could also be registered per route instead of being applied globally. Registering a handler per route means that the handler takes place only for some requests:
In this case, we are using the CustomHeaderMessageHandler only for the PostsController as shown in the route template.
Handlers play a central part in the architecture of the ASP.NET Web API. The ability to modify the request and the response outside the service opens interesting scenarios and gives the possibility to extend the default framework’s behavior.
In this chapter we looked at some basic background information about handlers and how to implement some custom handlers for specific circumstances.