Инъекция зависимостей с атрибутом Ninject и Filter для asp.net mvc
Я пишу пользовательский фильтр авторизации для asp.net mvc 3. Мне нужно ввести пользовательский сервис в класс, но я понятия не имею, как это сделать.
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 для внедрения зависимостей. Я не хочу использовать шаблон фабрики или локатора служб.
мои привязки в глобальной.acsx:
internal class SiteModule : NinjectModule
{
public override void Load()
{
Bind<IUserService>().To<UserService>();
}
}
4 ответа:
посмотреть этот ответ:
пользовательская авторизация MVC 3 и Ninject IoC
Если вы хотите использовать инъекцию конструктора, то вам нужно создать атрибут и фильтр.
///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 { }
НТН...
Я очень рекомендовать ответ B Z. не используйте [Inject]!
Я использовал [Inject], как сказал Дарин Димитров, это было возможно, и это на самом деле вызвало проблемы с потоками при высокой нагрузке, высокие конфликтные ситуации в сочетании .InRequestScope.
путь B Z-это также то, что находится на Вики, и я видел много мест, где Ремо Глор (автор Ninject) говорит, что это правильный способ сделать это
https://github.com/ninject/ninject.web.mvc/wiki/Filter-configurations
Downvote [Inject] ответы здесь, потому что серьезно вы получите сожжены (вероятно, в производстве, если вы не загружаете тест должным образом до!)
Я нашел простое решение для любого случая, когда конструкция не обрабатывается Ninject:
var session = (IMyUserService)DependencyResolver.Current.GetService(typeof (IMyUserService));
на самом деле это именно то, что я использую с моим пользовательским AuthorizeAttribute. Гораздо проще, чем реализовать отдельный FilterAttribute.
на пути было бы использовать инъекцию свойства и украсить свойство с :
public class AuthorizeAttribute : FilterAttribute, IAuthorizationFilter { [Inject] public IUserService UserService { get; set; } private string[] roles; ... }
инъекция конструктора не работает хорошо с атрибутами, так как вы больше не сможете украшать контроллеры/действия с ними. Вы можете использовать только инъекцию конструктора с синтаксисом привязки фильтра в 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; } ... }
и затем:
internal class SiteModule : Ninject.Modules.NinjectModule { public override void Load() { Bind<IUserService>().To<UserService>(); this.BindFilter<AuthorizeAttribute>(FilterScope.Controller, 0) .WhenControllerType<AdminController>(); } }
The
BindFilter<>
метод расширения, определенный вNinject.Web.Mvc.FilterBindingSyntax
пространство имен, поэтому убедитесь, что вы привели это в область видимости, прежде чем вызывать его на ядре.