Ninject and MVC3: Dependency injection to action filters
Asked Answered
C

2

20

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?

Cowgirl answered 22/2, 2011 at 12:23 Comment(0)
H
8

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.

Helot answered 22/2, 2011 at 13:1 Comment(3)
DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel)); - this line is not necessaty. NinjectHTTPApplication registers DependencyResolver in Application_Start.Monica
Rather annoying that Ninject have developed their own way of doing things which directly contradicts Microsoft's efforts, however this worked. Thanks.Cowgirl
Thanks a lot, that was very helpful.Ladanum
F
14

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/

Foresaid answered 22/2, 2011 at 21:0 Comment(0)
H
8

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.

Helot answered 22/2, 2011 at 13:1 Comment(3)
DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel)); - this line is not necessaty. NinjectHTTPApplication registers DependencyResolver in Application_Start.Monica
Rather annoying that Ninject have developed their own way of doing things which directly contradicts Microsoft's efforts, however this worked. Thanks.Cowgirl
Thanks a lot, that was very helpful.Ladanum

© 2022 - 2024 — McMap. All rights reserved.