left-icon

ASP.NET Web API Succinctly®
by Emanuele DelBono

Previous
Chapter

of
A
A
A

CHAPTER 8

Message Handlers

Message Handlers


Onion architecture

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:

public class CustomHeaderMessageHandler : DelegatingHandler

{

    protected override Task<HttpResponseMessage> SendAsync

                                 (

                                    HttpRequestMessage request,

                                    CancellationToken cancellationToken

                                 )

    {

        request.Headers.Add("X-My-custom-Header", "this is a custom header");

        return base.SendAsync(request, cancellationToken);

    }

}

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:

public class LogMessageHandler : DelegatingHandler

{

    protected override async Task<HttpResponseMessage> SendAsync

                                 (

                                    HttpRequestMessage request,

                                    CancellationToken cancellationToken

                                 )

    {

        HttpResponseMessage response = await base.SendAsync(request,

                                                          cancellationToken);

        if (!response.IsSuccessStatusCode)

        {

            // Log the error.

        }

        return response;

    }

}

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:

IHttpRoute route = config.Routes.CreateRoute(

    routeTemplate: "api/Posts/{id}",

    defaults: new HttpRouteValueDictionary("route"),

    constraints: null,

    dataTokens: null,

    handler: new CustomHeaderMessageHandler());

config.Routes.Add("WithHandler",route);

In this case, we are using the CustomHeaderMessageHandler only for the PostsController as shown in the route template.

Summary

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.

Scroll To Top
Disclaimer
DISCLAIMER: Web reader is currently in beta. Please report any issues through our support system. PDF and Kindle format files are also available for download.

Previous

Next



You are one step away from downloading ebooks from the Succinctly® series premier collection!
A confirmation has been sent to your email address. Please check and confirm your email subscription to complete the download.