dependency injection com atributo Ninject e Filter para asp.net mvc

Eu estou escrevendo um filtro de autorização personalizado para asp.net mvc 3. Eu preciso injetar um userservice na class, mas não tenho idéia de como fazer isso.

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(); } } 

Estou usando o ninject para injeção de dependência. Eu não quero usar um padrão de fábrica ou localizador de serviço.

Minhas ligações são assim no global.acsx:

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

    Veja esta resposta:

    Autorização Customizada MVC 3 e Ninject IoC

    Se você quiser usar injeção de construtor, precisará criar um atributo e um 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" } }); } } } 

    Obrigatório:

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

    Controlador:

     [MyAuthorizeAttribute] public class YourController : Controller { } 

    HTH …

    Eu recomendaria altamente a resposta de BZ. NÃO use [Inject]!

    Eu usei um [Inject] como Darin Dimitrov disse que era possível e ele realmente causou problemas de encadeamento sob alta carga, situações de alta contenção em conjunto com .InRequestScope.

    O caminho do BZ também é o que está no Wiki e eu vi muitos lugares onde Remo Gloor (autor do Ninject) diz que esta é a maneira correta de fazer isso.

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

    Downvote [Inject] responde aqui porque seriamente você vai se queimar (provavelmente em produção se você não carregar o teste corretamente antes!)

    No caminho seria usar uma injeção de propriedade e decorar a propriedade com o atributo [Inject] :

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

    A injeção de construtor não funciona bem com os atributos, pois você não poderá mais decorar controladores / ações com eles. Você só pode usar injeção de construtor com a syntax de vinculação de filtro no 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; } ... } 

    e depois:

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

    O método de extensão BindFilter<> é definido no espaço de nomes Ninject.Web.Mvc.FilterBindingSyntax portanto, certifique-se de tê-lo colocado no escopo antes de chamá-lo em um kernel.

    Eu encontrei uma solução simples para qualquer ocasião em que a construção não é tratada pela Ninject:

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

    Na verdade, é exatamente isso que estou usando com o meu AuthorizeAttribute personalizado. Muito mais fácil do que ter que implementar um FilterAttribute separado.