Dependency Injection for Handlers and Filters in ASP.NET Web API
Asked Answered
D

2

13

I am trying to wire up my Web Api project to use Castle Windsor for IoC

I have done that for my controllers by following this excellent article.

I am now trying to get dependencies injected into my DelegatingHandler and ActionFilterAttribute

I have tried to copy the techniques used for filters in regular ASP.Net MVC but they don't seem to apply in Web Api

has anyone managed to get this working?

I'm not sure what the relevant extension point is in the Web Api

I have seen this being suggested

config.MessageHandlers.Add(_myContainer.Resolve<IApiUsageLogger>());

but not sure if there is a better way. I would prefer to tap into the mechanism that creates these handlers/filters

As this smells of Service Location for lots of handlers. Is there a single point that all handlers are created?

any ideas?

Dreeda answered 24/10, 2012 at 16:42 Comment(1)
Link to the similar question: #10930902Centro
S
16

Since the MessageHandlers collection is global, it's effectively a list of singletons. 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.

Web API however lacks any hooks that allow to resolve such handler on each request, but such mechanism is easily created by using a proxy class:

public class DelegatingHandlerProxy<TDelegatingHandler> : DelegatingHandler
    where TDelegatingHandler : DelegatingHandler
{
    private readonly WindsorContainer container;

    public DelegatingHandlerProxy(WindsorContainer container)
    {
        this.container = container;
    }

    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        // trigger the creation of the scope.
        request.GetDependencyScope();

        var handler = this.container.Resolve<TDelegatingHandler>();

        handler.InnerHandler = this.InnerHandler;

        var invoker = new HttpMessageInvoker(handler);

        var response = await invoker.SendAsync(request, cancellationToken);

        container.Release(handler);

        return response;
    }
}

This proxy can be used as follows:

GlobalConfiguration.Configuration.MessageHandlers.Add(
    new DelegatingHandlerProxy<MyCustomHandler>(myContainer));

The proxy is a singleton, but it will resolve the specified MyCustomHandler on each request.

Sonometer answered 20/10, 2014 at 19:0 Comment(4)
sry to ask this so late here. i'm not familiar with castle windsor and want to do something similar with unity. what exactly is container.Release(handler); doing here ? is this mandatory ?Devisable
@cmxl: Release is a Castle.Windsor thing. There's no equivalent to Release in other containers, they don't require Release.Sonometer
thanks for the fast response. I have just implement your solution with unity and packed the handler instance in a using statement.Devisable
Thanks! That helped me a lot. I wish I could upvote a thousand times!Lee
S
0

There seems to be no extension point as of today. There is a request for it though, at http://aspnetwebstack.codeplex.com/workitem/62

Seamy answered 28/11, 2012 at 9:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.