Asp.net mvc asp.net mvc中带有Ninject和Filter属性的依赖项注入

Asp.net mvc asp.net mvc中带有Ninject和Filter属性的依赖项注入,asp.net-mvc,asp.net-mvc-3,ninject,Asp.net Mvc,Asp.net Mvc 3,Ninject,我正在为asp.net mvc 3编写一个自定义授权筛选器。我需要向类中注入userservice,但我不知道如何做到这一点 public class AuthorizeAttribute : FilterAttribute, IAuthorizationFilter { private IUserService userService; private string[] roles; public AuthorizeAttribute(params string[]

我正在为asp.net mvc 3编写一个自定义授权筛选器。我需要向类中注入userservice,但我不知道如何做到这一点

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进行依赖注入。我不想使用工厂或服务定位器模式

我的绑定在global.acsx中如下所示:

    internal class SiteModule : NinjectModule
    {
        public override void Load()
        {
            Bind<IUserService>().To<UserService>();
        }
    }
内部类SiteModule:NinjectModule
{
公共覆盖无效负载()
{
绑定()到();
}
}

方法是使用属性注入,并使用
[Inject]
属性装饰属性:

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>();
    }
}
内部类SiteModule:Ninject.Modules.Ninject模块
{
公共覆盖无效负载()
{
绑定()到();
此.BindFilter(FilterScope.Controller,0)
.WhenControllerType();
}
}
BindFilter
扩展方法是在
Ninject.Web.Mvc.FilterBindingSyntax
命名空间中定义的,因此在内核上调用它之前,请确保已将其纳入范围。

请参阅以下答案:

如果您想使用构造函数注入,那么您需要创建一个属性和一个过滤器

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

嗯…

我强烈推荐BZ的答案请勿使用[注入]

我使用了Darin Dimitrov所说的[Inject],它实际上会在高负载、高争用情况下与.InRequestScope一起导致线程问题

BZ的方式也是维基上的方式,我看到很多地方Remo Gloor(Ninject作者)说这是正确的方式


Downvote[Inject]在这里回答,因为严重的话,你会被烧死(如果你之前没有正确地进行负载测试,可能会在生产中!)

我找到了一个简单的解决方案,适用于Ninject没有处理构造的任何情况:

var session = (IMyUserService)DependencyResolver.Current.GetService(typeof (IMyUserService));
实际上,这正是我在自定义属性中使用的。
比必须实现单独的FilterAttribute容易得多。

您确定不想使用factory吗?在这种情况下,您必须在应用程序类中保留对内核的引用,并在控制器构造函数中手动获取()。在Mvc 3中,工厂确实有意义,因为您正在覆盖原始工厂。还有ninject NUGET。Jakubmal,你能用工厂来回答吗?如果我不使用构造函数绑定并使用
[Inject]
属性,我能装饰控制器/动作吗?知道
用户服务
为什么仍然为空吗?我对
提供者也有同样的问题。@Lol coder,不知道。对我来说很好。我创建了一个新的ASP.NET MVC 3应用程序,安装了NInject.MVC3 NuGet包,声明了一个IUserService接口和UserService实现,使用属性注入声明了一个自定义的MyAuthorizeAttribute,并使用生成的
App_Start/NinjectMVC3.cs
来配置内核。然后我简单地用属性装饰了我的HomeController,注入效果很好。感谢您指定名称空间!!!必须找到扩展方法所需的名称空间,这很烦人!我强烈推荐BZ的答案。不要使用[Inject],它会在高负载下造成竞争条件!您将如何设置实现以适应:
[MyAuthorizeAttribute(“Admin”、“Contributer”)]
?传递参数+1用于给出支持构造函数而不是属性的答案Injection@Lol编码器-有关如何配置筛选器,请参阅上面的Remo链接。我仍然不知道如何设置属性构造函数以同时接受参数和服务。我阅读了配置。。。仍然无法找出如何将属性构造函数参数获取到筛选器的构造函数参数。。。我错过了一些东西。类似的问题:我做了,没有人会看到它,因为默认情况下它是隐藏的(太深了)。基于我花了3天时间试图找出Darin的答案出了什么问题的事实,我认为这是非常相关的,值得一个正式的答案,以避免任何人错误地使用它并被烧死
var session = (IMyUserService)DependencyResolver.Current.GetService(typeof (IMyUserService));