为asp.net mvc提供Ninject和Filter属性的dependency injection
我正在为asp.net mvc 3编写一个自定义的授权filter。我需要注入一个用户服务到类,但我不知道如何做到这一点。
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(); } }
我使用ninject进行dependency injection。 我不想使用工厂或服务定位器模式。
我的绑定在global.acsx中看起来像这样:
internal class SiteModule : NinjectModule { public override void Load() { Bind<IUserService>().To<UserService>(); } }
看到这个答案:
自定义授权MVC 3和Ninject IoC
如果你想使用构造函数注入,那么你需要创build一个属性和一个filter。
///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" } }); } } }
捆绑:
this.BindFilter<MyAuthorizeFilter>(System.Web.Mvc.FilterScope.Controller, 0).WhenControllerHas<MyAuthorizeAttribute>();
控制器:
[MyAuthorizeAttribute] public class YourController : Controller { }
HTH …
我强烈推荐BZ的答案。 不要使用[Inject]!
我使用了像Darin Dimitrov所说的[Inject],这是可能的,它实际上在高负载,高争用情况下与.InRequestScope一起引起了线程问题。
BZ的方式也是在维基上,我已经看到许多地方,雷莫尔(Ninject的作者)说,这是正确的方式来做到这一点
https://github.com/ninject/ninject.web.mvc/wiki/Filter-configurations
Downvote [Inject]在这里的答案,因为严重的你会被烧毁(如果你没有正确加载testing之前可能在生产!)
在途中将是使用属性注入并用[Inject]
属性装饰属性:
public class AuthorizeAttribute : FilterAttribute, IAuthorizationFilter { [Inject] public IUserService UserService { get; set; } private string[] roles; ... }
构造函数注入不能很好地使用属性,因为你将不再能够用它们来装饰控制器/动作。 您只能在NInject中使用带有filter绑定语法的构造函数注入:
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; } ... }
接着:
internal class SiteModule : Ninject.Modules.NinjectModule { public override void Load() { Bind<IUserService>().To<UserService>(); this.BindFilter<AuthorizeAttribute>(FilterScope.Controller, 0) .WhenControllerType<AdminController>(); } }
BindFilter<>
扩展方法在Ninject.Web.Mvc.FilterBindingSyntax
命名空间中定义,因此请确保在调用内核之前已将其引入到作用域中。
我发现一个简单的解决scheme,任何Ninject不能处理的场合:
var session = (IMyUserService)DependencyResolver.Current.GetService(typeof (IMyUserService));
其实这正是我用我的自定义AuthorizeAttribute。 比实现一个单独的FilterAttribute容易得多。