Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 390
ChrisCa Avatar asked Oct 24 '12 16:10

ChrisCa


People also ask

What is dependency injection in Web API?

“ - In software development, dependency injection is a technique where one object supplies the needs, or dependencies, of another object.

What are filters in asp net Web API?

Web API includes filters to add extra logic before or after action method executes. Filters can be used to provide cross-cutting features such as logging, exception handling, performance measurement, authentication and authorization.

Does ASP NET support dependency injection?

ASP.NET Core supports the dependency injection (DI) software design pattern, which is a technique for achieving Inversion of Control (IoC) between classes and their dependencies. For more information specific to dependency injection within MVC controllers, see Dependency injection into controllers in ASP.NET Core.

Can we inject dependency in Viewcomponent?

A view component class: Supports constructor dependency injection. Doesn't take part in the controller lifecycle, therefore filters can't be used in a view component.


1 Answers

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.

like image 122
Steven Avatar answered Sep 20 '22 15:09

Steven