10

I can't get dependency injection working with a custom ActionFilterAttribute class using the Unity bootstrapper for ASP.NET Web API nuget package.

I've registered the type in UnityConfig and I'm using it elsewhere (using constructor injection there though) and it works fine.

public static void RegisterTypes(IUnityContainer container)
{
    container.RegisterType<ISettingService, SettingService>();
    ...
}

The code is being called successfully, however the instantiated object (settingService) is null.

public class APIKeyValidationAttribute : ActionFilterAttribute
{
    [Dependency]
    public ISettingService settingService { get; set; }

public override void OnActionExecuting(HttpActionContext actionContext)
{
    ...
    if (settingService == null)
    {
        throw new Exception("settingService is null");
    }
    ...
}

What do I need to do to get this working? I've been searching for a long time and can only find examples for MVC or for Web API with different dependency injectors.

1 Answer 1

11

First create an IFilterProvider that will perform a BuildUp and inject the dependencies:

public class UnityActionFilterProvider 
    : ActionDescriptorFilterProvider, IFilterProvider
{
    private readonly IUnityContainer container;

    public UnityActionFilterProvider(IUnityContainer container)
    {
        this.container = container;
    }

    public new IEnumerable<FilterInfo> GetFilters(
        HttpConfiguration configuration, 
        HttpActionDescriptor actionDescriptor)
    {
        var filters = base.GetFilters(configuration, actionDescriptor);

        foreach (var filter in filters)
        {
            container.BuildUp(filter.Instance.GetType(), filter.Instance);
        }

        return filters;
    }
}

Then register the IFilterProvider:

private static void RegisterFilterProviders()
{
    var providers = 
        GlobalConfiguration.Configuration.Services.GetFilterProviders().ToList();

    GlobalConfiguration.Configuration.Services.Add(
        typeof(System.Web.Http.Filters.IFilterProvider),
        new UnityActionFilterProvider(UnityConfig.GetConfiguredContainer()));

    var defaultprovider = providers.First(p => p is ActionDescriptorFilterProvider);

    GlobalConfiguration.Configuration.Services.Remove(
        typeof(System.Web.Http.Filters.IFilterProvider), 
        defaultprovider);
}

I put this method and invoked it in the UnityWebApiActivator class.

Sign up to request clarification or add additional context in comments.

6 Comments

Thanks heaps Tuzo. I have created a new class, added the RegisterFilterProviders method into the UnityWebApiActivator class add added the namespace for the new class. This error is produced 'System.Collections.Generic.IEnumerable<System.Web.Http.Filters.IFilterProvider>' does not contain a definition for 'ToList' and no extension method 'ToList' accepting a first argument of type 'System.Collections.Generic.IEnumerable<System.Web.Http.Filters.IFilterProvider>' could be found (are you missing a using directive or an assembly reference?) is there any other namespaces that I need to add in?
@MichaelS: ToList() is an extension method in System.Linq. Add using System.Linq; to the top of your file to resolve that compile error.
Thanks that worked fine. For some reason there was no "Resolve" option when I right clicked on it.
Very useful! @Tuzo, where did you come up with this stuff? I'd like to have a read myself. Thank you!
@RandyLevy I have tried your solution but for me, ISettingService is always null, can you help me?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.