Ninject and MVC3: Dependency injection to action filters

I've found loads of inconclusive articles and questions on how to do property injection on an ActionFilter in ASP.NET MVC3 using Ninject.

Could someone give me a clear example please?

Here's my custom auth attribute.

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    [Inject]
    public IService Service { get; set; }

    [Inject]
    public IAuthenticationHelper AuthenticationHelper { get; set; }

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
         //My custom code
    }
 }

I am using the WebActivator to set up Ninject

[assembly: WebActivator.PreApplicationStartMethod(typeof(MyProject.Web.AppStart_NinjectMvc3), "Start")]

 namespace MyProject.Web {

   public static class AppStart_NinjectMvc3 {
        public static void RegisterServices(IKernel kernel) {

           //Binding things
    }

    public static void Start() {
        // Create Ninject DI Kernel 
        IKernel kernel = new StandardKernel();

        // Register services with our Ninject DI Container
        RegisterServices(kernel);

        // Tell ASP.NET MVC 3 to use our Ninject DI Container 
        DependencyResolver.SetResolver(new NinjectServiceLocator(kernel));
    }

  }
}

My service and helper are never injected. What do I need to change?

Answers


Here's how you could proceed:

public class MvcApplication : Ninject.Web.Mvc.NinjectHttpApplication
{
    private class MyModule : NinjectModule
    {
        public override void Load()
        {
            Bind<IService>().To<ServiceImpl>();
            Bind<IAuthenticationHelper>().To<AuthenticationHelperImpl>();
        }
    }

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

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            "Default",
            "{controller}/{action}/{id}",
            new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }

    protected override void OnApplicationStarted()
    {
        AreaRegistration.RegisterAllAreas();

        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);
    }

    protected override IKernel CreateKernel()
    {
        var modules = new INinjectModule[] {
            new MyModule()
        };
        var kernel = new StandardKernel(modules);
        DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));
        return kernel;        
    }
}

and then you could have your custom authorize attribute:

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    [Inject]
    public IService Service { get; set; }

    [Inject]
    public IAuthenticationHelper AuthenticationHelper { get; set; }

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
    }
}

and a controller action decorated with it:

[CustomAuthorize]
public ActionResult Index()
{
    return View();
}

and the dependencies should be injected.


In my opinion there is a better solution than using filter attributes. See my blogposts about an alternative way of declaring filters using Ninject. It does not require property injection and uses constructor injection instead:

http://www.planetgeek.ch/2010/11/13/official-ninject-mvc-extension-gets-support-for-mvc3/ http://www.planetgeek.ch/2011/02/22/ninject-mvc3-and-ninject-web-mvc3-merged-to-one-package/


Need Your Help

Combine expander and grid (resizable expander)

wpf xaml grid expander gridsplitter

I would like to have something like a resizable Expander. My basic idea was something like this:

IOS 10.3.1 Chrome browser CORS fail

javascript ios google-chrome cors ios10.3

I ve been experiencing a strange error while doing CORS requests from my website (React app talking to APIs over https). The errors appear only on IOS 10.3.1 and on the Chrome browser (57) (safari ...