Simple Injector property injection on action filter

David McLean picture David McLean · Aug 23, 2012 · Viewed 8.3k times · Source

The action filter I want to inject into starts like this

public class UserAuthorisation : AuthorizeAttribute
{
    public IWcfClientProxy<IAppFrameworkServiceChannel>
        FrameworkServiceProxy { get; set; }

I have setup my container like this:

container.Register<IWcfClientProxy<IAppFrameworkServiceChannel>>(
    ()=> new WcfClientProxy<IAppFrameworkServiceChannel>());

container.RegisterInitializer<UserAuthorisation>(handler =>
{
    handler.FrameworkServiceProxy = container
       .GetInstance<IWcfClientProxy<IAppFrameworkServiceChannel>>();
});

When I run this the FrameworkServiceProxy property is null.

I have read this post: Simple Injector: Injecting a property in a base class and followed the answer. I have also read example in this page Simple Injector Documentation.

I am not injecting into a base class and maybe that is the issue?

## UPDATE ##

I am adding more information as I think it should be working from what has been said in Stevens answer.

I am using the NuGet package for MVC 3. This adds the following to the application:

public static class SimpleInjectorInitializer
{
    /// <summary>Initialize the container and register it as MVC3 Dependency Resolver.</summary>
    public static void Initialize()
    {
        var container = new Container();
        InitializeContainer(container);
        container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
        container.RegisterMvcAttributeFilterProvider();
        container.Verify();
        DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
    }

    private static void InitializeContainer(Container container)
    {
        container.Register<IWcfClientProxy<IAppFrameworkServiceChannel>>(() => new WcfClientProxy<IAppFrameworkServiceChannel>());
        container.RegisterInitializer<UserAuthorisation>(handler =>
            {
                handler.FrameworkServiceProxy = container.GetInstance<IWcfClientProxy<IAppFrameworkServiceChannel>>();
            });
    }

This includes the container.RegisterMvcAttributeFilterProvider(); that as I now understand it should register a filter provider and should mean that filters are created through the container (this understanding might be wrong) and then properties are automatically wired-up.

My filter is registered in the Global.asax.cs like so:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute());
    filters.Add(new UserAuthorisation());
}

It seems to me that the filter is not being created by the container so I think I need to do something else to get that to happen ?

Answer

David McLean picture David McLean · Aug 24, 2012

I have selected Stevens answer as the answer as it got me to a solution and I am now using the command handler that he mentioned in the comments.

I have put a simple work around in to get my global filters injected.

In the App_Start\SimpleInjectorInitializer.cs I have added RegisterGlobalFilters like this:

public static void RegisterGlobalFilters(GlobalFilterCollection filters, Container container)
{
    //Add simple injector resolved types.
    filters.Add(container.GetInstance<UserAuthorisation>());
}

And in the Initialize method I have added this RegisterGlobalFilters(GlobalFilters.Filters, container);

The complete method looks like this:

/// <summary>Initialize the container and register it as MVC3 Dependency Resolver.</summary>
public static void Initialize()
{
    var container = new Container();
    InitializeContainer(container);
    container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
    container.RegisterMvcAttributeFilterProvider();
    container.Verify();
    DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));

    RegisterGlobalFilters(GlobalFilters.Filters, container);
}

As I said very simple. Just get my instances from simple injector and then add them to the global list, I am sure there are better ways to do this.

This way does mean you do not need to change the global.asax.cs which is possibly a good thing.