Как использовать Ninject для внедрения сервисов в фильтр авторизации?
Я использую asp.net mvc 3, ninject 2.0 и плагин ninject mvc 3.
Мне интересно, как я могу добавить служебные слои в мой фильтр (в данном случае фильтр авторизации?).
Мне нравится делать конструктор инъекций, так это возможно, или я должен вводить свойства?
Спасибо
редактировать
У меня есть это для ввода свойства, но моя собственность всегда равна нулю
[Inject]
public IAccountService AccountServiceHelper { get; set; }
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
// check if context is set
if (httpContext == null)
{
throw new ArgumentNullException("httpContext");
}
// check if user is authenticated
if (httpContext.User.Identity.IsAuthenticated == true)
{
// stuff here
return true;
}
return false;
}
/// <summary>
/// Application_Start
/// </summary>
protected void Application_Start()
{
// Hook our DI stuff when application starts
IKernel kernel = SetupDependencyInjection();
RegisterMaps.Register();
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
public IKernel SetupDependencyInjection()
{
IKernel kernel = CreateKernel();
// Tell ASP.NET MVC 3 to use our Ninject DI Container
DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));
return kernel;
}
protected IKernel CreateKernel()
{
var modules = new INinjectModule[]
{
new NhibernateModule(),
new ServiceModule(),
new RepoModule()
};
return new StandardKernel(modules);
}
public class ServiceModule : NinjectModule
{
public override void Load()
{
Bind<IAccountService>().To<AccountService>();
}
}
редактировать
Я обновился до версии 2.2, и наконец-то все заработало.
Редактировать 2
Я собираюсь попробовать конструктор для моего авторизационного фильтра, но я не уверен, как передать роли. Я предполагаю, что я должен сделать это через ninject?
Редактировать 3
Это то, что я до сих пор
public class MyAuthorizeAttribute : AuthorizeAttribute
{
private readonly IAccountService accountService;
public MyAuthorizeAttribute(IAccountService accountService)
{
this.accountService = accountService;
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
return base.AuthorizeCore(httpContext);
}
}
this.BindFilter<MyAuthorizeAttribute>(FilterScope.Controller, 0)
.WhenControllerHas<MyAuthorizeAttribute>();
[MyAuthorize]
public class MyController : BaseController
{
}
Он говорит мне, что хочет конструктор без параметров. Так что я должен что-то упустить.
2 ответа
Проблема с фильтрами заключается в том, что они являются атрибутами. И если вы определите конструктор атрибута, который ожидает некоторую зависимость, вы никогда не сможете применить его к любому методу: потому что все значения, которые вы передаете атрибутам, должны быть известны во время компиляции.
В общем, у вас есть две возможности:
Используйте Ninject, чтобы применить фильтр глобально, вместо того, чтобы украшать его контроллерами / действиями:
public interface IFoo { } public class Foo : IFoo { } public class MyFooFilter : AuthorizeAttribute { public MyFooFilter(IFoo foo) { } }
а затем настройте ядро:
kernel.Bind<IFoo>().To<Foo>(); kernel.BindFilter<MyFooFilter>(FilterScope.Action, 0).When( (controllerContext, actionDescriptor) => string.Equals( controllerContext.RouteData.GetRequiredString("controller"), "home", StringComparison.OrdinalIgnoreCase ) );
Используйте свойство инъекции:
public interface IFoo { } public class Foo : IFoo { } public class MyFooFilter : AuthorizeAttribute { [Inject] public IFoo Foo { get; set; } }
а затем настройте ядро:
kernel.Bind<IFoo>().To<Foo>();
и украсить некоторый контроллер / действие с вашим собственным фильтром:
[MyFooFilter] public ActionResult Index() { return View(); }
Смотрите этот вопрос / ответ здесь:
Настройте атрибут фильтра для внедрения зависимости, чтобы принимать параметры в конструкторе
и здесь
Внедрение зависимостей с атрибутом Ninject и Filter для asp.net mvc