13

This MSDN article describes how HTTP Message Handlers can effectively be used in ASP.NET Web API to 'decorate' requests. Furthermore, the article shows the following code to register your custom handlers into the Web API pipeline:

config.MessageHandlers.Add(new MessageHandler1());

The problem I have with this approach is that this registers the MessageHandler1 effectively as a singleton. This is fine when the handler itself has no state and no dependencies, but in a system that is based on the SOLID design principles, it's very likely that those handlers will have dependencies of their own and its very likely that some of those dependencies need a lifetime that is shorter than singleton.

If that's the case, such message handler should not be created as singleton, since in general, a component should never have a lifetime that is longer than the lifetime of its dependencies.

So my question is, what alternative ways do we have to register custom message handlers, in such way that they can be resolved from our IoC container on each request?

Steven
  • 166,672
  • 24
  • 332
  • 435
  • What IOC container you use? Depending on the container it is pretty easy to resolve an instance that can be resolved per request.Some containers have built in lifetime managers. http://msdn.microsoft.com/en-us/library/microsoft.practices.unity.perrequestlifetimemanager(v=pandp.30).aspx or you can create your own one. – Spock Dec 10 '13 at 02:00
  • @Spock: Every mainstream container has support of lifestyles such as Per Web Request, so registering a messaging handler with a per-request lifestyle is easy. The question though is how to make sure that such handler is resolved on each request. I explicitly didn't note my container, since I believe this irrelevant to the question. – Steven Dec 10 '13 at 08:03
  • 1
    Sorry actually when read it again it make sense. A good question though. Honestly don't know the exact answer but the below link might help you in some way, I'm glad. I booked marked this question hopefully someone answer this question. http://stackoverflow.com/questions/4821108/dependency-injection-what-if-dependency-lifetimes-are-shorter-than-the-depende – Spock Dec 10 '13 at 10:14

2 Answers2

5

I'm not aware of a different registration API for message handlers, but you can inject a Factory into your message handler in order to make it resolve dependencies per method call:

public class LifetimeProxyMessageHandler : DelegatingHandler
{
    private readonly IHttpMessageHandlerFactory factory;

    public LifetimeProxyMessageHandler(IHttpMessageHandlerFactory factory)
    {
        if (factory == null)
            throw new ArgumentNullException("factory");
        this.factory = factory;
    }

    protected override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        HttpMessageHandler ephemeralHandler = factory.Create();

        ephemeralHandler.InnerHandler = this.InnerHandler;

        var invoker = new HttpMessageInvoker(ephemeralHandler);

        return invoker.SendAsync(request, cancellationToken);
    }
}

You might want to skip having an ephemeral HttpMessageHandler, and instead just ask the factory to create an instance of whatever service you wish to invoke at that point.

IHttpMessageHandlerFactory is a custom interface I just made up for the occasion. It could look like this:

public interface IHttpMessageHandlerFactory
{
    HttpMessageHandler Create();
}
Steven
  • 166,672
  • 24
  • 332
  • 435
Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
  • Thank you Mark. Having a proxy crossed my mind, but couldn't imagine not missing something obvious. I expected Web API to supply an extension point to allow this. – Steven Dec 10 '13 at 11:00
  • Hey @Steven, Mark: do you have any update on this topic since that? Especially regarding the support in SI. – abatishchev Oct 20 '14 at 17:49
  • @abatishchev: anything specific you're wondering? Might be good to start a new question here at stackoverflow. – Steven Oct 20 '14 at 17:55
  • @Steven: I mean maybe modern containers, especially SI, provide a more convenient way to inject dependencies into handlers? Per application or per request (somewhat opposite to the built-in flow, per my understanding). – abatishchev Oct 20 '14 at 18:21
  • @abatishchev: ask a new question and I'll show you. – Steven Oct 20 '14 at 18:22
  • @Steven: There is old and unanswered question with pretty good title already: [Dependency Injection for Handlers and Filters in ASP.NET Web API](http://stackoverflow.com/questions/13053734/dependency-injection-for-handlers-and-filters-in-asp-net-web-api). My question is about both Web API and MVC though. It's not a problem to ask a new question still. – abatishchev Oct 20 '14 at 18:25
  • Also it mentions Mark's article, so all-in-one :) – abatishchev Oct 20 '14 at 18:29
  • @abatishchev: Since the question is about Castle, my answer is as well, but here's an implementation for Simple Injector: https://simpleinjector.readthedocs.org/en/latest/webapiintegration.html#injecting-dependencies-into-web-api-message-handlers – Steven Oct 20 '14 at 19:29
3

Taking cue from this article, I solved the same problem in the following way:

I created a service that will host my global variabile

public interface IPerRequestScopedService : IDisposable
{
    string ClientId { get; set; }
}

public class PerRequestScopedService : IPerRequestScopedService
{
    public string ClientId { get; set; }

    public void Dispose()
    {
        Trace.TraceInformation("Object {0} disposed", this.GetType().Name);
    }
}

Then I registered it in my IoC container (in my case is SimpleInjector) using per request lifetime

container.RegisterWebApiRequest<IPerRequestScopedService, PerRequestScopedService>();

Then I used the service inside the DelegatingHandler in this way

public class HeaderReaderHandler : DelegatingHandler
{
    protected async override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        Trace.TraceInformation("start HeaderReaderHandler");

        IEnumerable<string> headerValues;
        if (request.Headers.TryGetValues("x-client-id", out headerValues))
        {
            string token = headerValues.First();
            var requestScopedService = request.GetDependencyScope().GetService(typeof(IPerRequestScopedService)) as IPerRequestScopedService;
            requestScopedService.ClientId = token;
        }

        // Call the inner handler.
        var response = await base.SendAsync(request, cancellationToken);
        return response;
    }
}

I chose this implementation over the Factory because I think is more IoC oriented even if is using Service Locator pattern instead of full Dependency Injection.

ilcorvo
  • 446
  • 5
  • 18