Ninject绑定属性到具有构造函数参数的过滤器

18

我尽可能地阅读了许多答案,但它们似乎缺少一个细节。

问题在于,当将一个带有由控制器注入的服务绑定的操作过滤器绑定到相应的属性时,我无法弄清楚如何从属性中传递参数/属性值到其绑定的过滤器。以下是代码,以及我打算使用的虚拟代码:

过滤器和属性

public class AuthorizationFilter : IAuthorizationFilter
{
    private readonly IAuthorizationService _authorizationService;
    private readonly UserRoles _requiredRoles;   // Enum

    public AuthorizationFilter(IAuthorizationService authorizationService, UserRoles requiredRoles)
    {
        _authorizationService = authorizationService;
        _requiredRoles = requiredRoles;
    }

    public void OnAuthorization(AuthorizationContext filterContext)
    {
        if (filterContext.HttpContext.Session == null)
            HandleUnauthorizedRequest(filterContext);
        else {
            var authorized = _authorizationService.IsUserInRole((UserSessionInfoViewModel) filterContext.HttpContext.Session["user"], _requiredRoles);
            if (!authorized)
                HandleUnauthorizedRequest(filterContext);
            // else TODO: deal with cache... 
        }
    }
}

public class RequireRolesAttribute : FilterAttribute
{
    public readonly UserRoles RequiredRoles;

    public RequireRolesAttribute(UserRoles requiredRoles)
    {
        RequiredRoles = requiredRoles;
    }        
}

筛选器/属性绑定

kernel.BindFilter<AuthorizationFilter>(FilterScope.Controller, 0)
      .WhenControllerHas<RequireRolesAttribute>();
kernel.BindFilter<AuthorizationFilter>(FilterScope.Action, 0)
      .WhenActionMethodHas<RequireRolesAttribute>();

这应该确保任何使用[RolesRequired]装饰的控制器/操作都绑定到筛选器。 到目前为止,一切正常。 现在我想通过属性声明角色(与默认AuthorizeAttribute类似),并将这些值传递给实际执行授权的筛选器。

意图/虚假代码:

[RequireRoles(UserRoles.Author)]
public ActionResult Index()
{
    // blah
}

具体来说,

如何通知AuthorizationFilter角色信息?过滤器/尼克支持访问属性构造函数传递的参数吗?过滤器/尼克能否从属性公共属性中提取它们?

参考这些文章是很有帮助的,但并不能回答这个问题:

使用Ninject和ASP.NET MVC的Filter属性进行依赖注入

自定义授权MVC 3和Ninject IoC

B Z、Remo Gloor和其他人……我该怎样实现它?

2个回答

21
我已经解决了这个问题(感谢Remo的指导和文档)。
无论您是绑定到控制器还是操作筛选器,都要使用适当的`.WithConstructorArgument`扩展。例如,绑定我的操作筛选器如下所示:
kernel.BindFilter<AuthorizationFilter>(FilterScope.Action, 0)
      .WhenActionMethodHas<RequireRolesAttribute>()
      .WithConstructorArgumentFromActionAttribute<RequireRolesAttribute>("requiredRoles", o => o.RequiredRoles);
一旦我理解了 Func<> 签名,一切都变得清晰起来。我发现处理这个最好的方法是:
  1. 将扩展方法针对我的属性进行类型特定

    .WithConstructorArgumentFromActionAttribute<TAttribute>()
    
  2. 通过lambda从回调对象中获取值(您的属性):

  3. ("argumentName", o => o.PropertyName)
    

如果从 FilterAttribute 派生的类具有多个参数的构造函数(例如上面示例中具有多个参数的 RequireRoles 类),则在 .WithConstructorArgumentFromActionAttribute<TAttribute>() 中如何映射这些参数? - Vipresh
1
要使BindFilter<>()方法可用,您可以添加对Ninject.Web.Mvc.FilterBindingSyntax的引用。 - Aage

10

并且要将 BindFilter 扩展方法引入到作用域中,请不要忘记添加;

using Ninject.Web.Mvc.FilterBindingSyntax;

16
这不是一个答案,应该作为对解决方案答案的评论发布。 - angularsen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接