Message handlers scoped per route in ASP.NET Web API - StrathWeb

Strath

August 11th, 2013

Message handlers scoped per route in ASP.NET Web API

A lot of Web API functionalities are based around message handlers. The real power of them is that they run for every request and provide an easy mechanism of globally addressing some of the application concerns (such as i.e. security). However, there are situations where you’d like to use a handler to apply specific behavior to only a selected portion of an application.

Let’s have a look at how you’d do it with route-specific message handlers

Suppose we have a need to log all traffic against the routes /api/[something] but not /api/public/[something]. As a result we need to have a message handler to apply only for a specific route, rather than globally to every request.

Route specific handlers

It is possible to configure a message handler (DelegatingHandler) on a per-route basis, rather than registering globally in a HttpConfigration object.

To begin with, let’s take a simple API request logging handler:

The actual implementation of the request/response logging is not important here. We are really interested only in the mechanism that will allow us to apply this handler to specific routes.

We do that in the Web API RouteConfig class:

There is an overload on the MapHttpRoute, in the HttpRouteCollectionExtensions that allows us to do that:

Notice that we need to specify the HttpControllerDispatcher as the inner handler for our handler – this means it will be chained as the next one to execute, and that’s the class responsible for creating controllers and continuing with the Web API execution pipeline. Using this technique, we could chain as many handlers on this route as we want, as long as we plug the HttpControllerDispatcher at the end.

How does it work?

In the Web API pipeline, the additional per route handler kicks after all global message handlers run and just prior to HttpControllerDispatcher. An HttpRoutingDispatcher is responsible solely for recognizing whether a given route has a specific handler attached to it, and if so, it will be run; otherwise the processing continues normally towards dispatching of controllers.

If you now run your application:

  • – all /public/api/[something] routes do not log their requests/responses
  • – all /api/[something] routes log their requests/responses – because the handler executes only for these routes

You can only imagine the amount of flexibility this gives the developers, especially in authentication and logging-related situations, where only specific routes have to be secured by authentication mechanisms (which are normally handled in Web API by message handlers) or should be subject to quotas or usage limits.

Be Sociable, Share!