Inyección de dependencia con el atributo Ninject y filtro para asp.net mvc

Estoy escribiendo un filtro de autorización personalizado para asp.net mvc 3. Necesito inyectar un servicio de usuario en la clase, pero no tengo idea de cómo hacerlo.

public class AuthorizeAttribute : FilterAttribute, IAuthorizationFilter { private IUserService userService; private string[] roles; public AuthorizeAttribute(params string[] roles) { this.roles = roles; } public void OnAuthorization(AuthorizationContext filterContext) { throw new NotImplementedException(); } } 

Estoy usando ninject para dependency injection. No quiero utilizar un patrón de localizador de fábrica o de servicio.

Mis enlaces se ven así en global.acsx:

  internal class SiteModule : NinjectModule { public override void Load() { Bind().To(); } } 

Ver esta respuesta:

Autorización personalizada MVC 3 y Ninject IoC

Si desea utilizar la inyección de constructor, debe crear un atributo y un filtro.

 ///marker attribute public class MyAuthorizeAttribute : FilterAttribute { } //filter public class MyAuthorizeFilter : IAuthorizationFilter { private readonly IUserService _userService; public MyAuthorizeFilter(IUserService userService) { _userService = userService; } public void OnAuthorization(AuthorizationContext filterContext) { var validUser = _userService.CheckIsValid(); if (!validUser) { filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary { { "action", "AccessDenied" }, { "controller", "Error" } }); } } } 

Unión:

 this.BindFilter(System.Web.Mvc.FilterScope.Controller, 0).WhenControllerHas(); 

Controlador:

 [MyAuthorizeAttribute] public class YourController : Controller { } 

HTH …

Recomiendo encarecidamente la respuesta de BZ. NO use [Inyectar]!

Usé un [Inyectar] como Darin Dimitrov dijo que era posible y que en realidad causó problemas de subprocesos en situaciones de alta carga y alta contención junto con .InRequestScope.

El camino de BZ también está en la Wiki y he visto muchos lugares donde Remo Gloor (autor de Ninject) dice que esta es la forma correcta de hacerlo

https://github.com/ninject/ninject.web.mvc/wiki/Filter-configurations

Downvote [Inyectar] respuestas aquí porque en serio te quemarás (¡probablemente en producción si no cargas la prueba correctamente antes!)

En el camino sería usar una inyección de propiedad y decorar la propiedad con el atributo [Inject] :

 public class AuthorizeAttribute : FilterAttribute, IAuthorizationFilter { [Inject] public IUserService UserService { get; set; } private string[] roles; ... } 

La inyección de Constructor no funciona bien con los atributos, ya que ya no podrá adornar los controladores / acciones con ellos. Solo se podía usar la inyección de constructor con la syntax de enlace de filtro en NInject:

 public class AuthorizeAttribute : FilterAttribute, IAuthorizationFilter { private readonly IUserService userService; private string[] roles; public AuthorizeAttribute(IUserService userService, params string[] roles) { this.userService = userService; this.roles = roles; } ... } 

y entonces:

 internal class SiteModule : Ninject.Modules.NinjectModule { public override void Load() { Bind().To(); this.BindFilter(FilterScope.Controller, 0) .WhenControllerType(); } } 

El método de extensión BindFilter<> se define en el espacio de nombres Ninject.Web.Mvc.FilterBindingSyntax así que asegúrese de haberlo incluido en el scope antes de llamarlo a un kernel.

Encontré una solución simple para cualquier ocasión donde Ninject no maneja la construcción:

 var session = (IMyUserService)DependencyResolver.Current.GetService(typeof (IMyUserService)); 

En realidad, esto es exactamente lo que estoy usando con mi AuthorizeAttribute personalizado. Mucho más fácil que tener que implementar un FilterAttribute separado.