如何在ASP.NET MVC中将存储库传递给授权属性

5

我是Castle Windsor,对于控制器构造函数中传递正在使用的存储库,它非常有效。

private IStoryRepository Repository;
public StoryController(IStoryRepository Repository)
{
    this.Repository = Repository;                   
}

现在我有一个在管理员区域显示主要管理员菜单的操作。我使用了一个自定义授权属性,它只会检查已登录用户是否是管理员(在用户表中只是一个isAdmin标志)。

 [AdminAuthorize]
 public ActionResult Menu()

 private IStoryRepository Repository;
 /// <summary>
 /// Initializes a new instance of the <see cref="AdminAuthorizeAttribute"/> class.
 /// </summary>
 public AdminAuthorizeAttribute(IStoryRepository Repository)
 {
     this.Repository = Repository;
 }

 /// <summary>
 /// Checks if the user is authorised
 /// </summary>
 /// <param name="httpContext">The HTTP context.</param>
 /// <returns>
 ///    <c>true</c> if authorized; otherwise, <c>false</c>.
 /// </returns>
 protected override bool AuthorizeCore(HttpContextBase httpContext)
 {
    return this.Repository.UserIsAdmin(httpContext.User.Identity.Name);
 }

如何让Castle像控制器构造函数一样将存储库传递到属性构造函数中?
4个回答

1

你基本上有两个选择。第一种是在代理中包装过滤器,这里可以找到一个很好的例子here

或者,在你的自定义过滤器中,你可以进行显式容器调用。例如使用StructureMap(我没有广泛使用过Castle)

ObjectFactory.GetInstance(IStoryRepository)

可能还有第三种方法,就是扩展ActionInvoker进行注入,但我不确定应该如何实现。


0

也许值得看一下FluentMVC项目。它允许你在启动时配置属性,并且因为它在内部使用了windsor,所以这应该很容易被注入。例如

FluentMvcConfiguration.Configure = x => {
                                 x.UsingControllerFactory(new WindsorControllerFactory());                                                                x.WithFilter<HandleErrorAttribute>();
                                 x.WithFilter<AuthorizeAttribute>(
                                     Except
                                         .For<AccountController>(ac => ac.LogOn())
                                         .AndFor<AccountController>(ac => ac.LogOn(null, null, false, null))
                                         .AndFor<HomeController>());
                             };

以上代码将在除了登录和主页控制器之外的所有操作中添加AuthorizeAttribute。

不确定项目当前状态如何,但我已经使用过几次,对我来说效果还不错。


0
问题在于属性是通过反射构建的,而不是通过可以拦截并替换为委托到容器的调用进行构建。
有许多方法可用于创建支持DI的过滤器,我认为最简单的方法是扩展操作调用程序并覆盖GetFilters,提供一个实现,该实现使用属性确定过滤器类型,然后从容器中解析该类型。此方法的实现可以在MvcTurbine中看到(http://mvcturbine.codeplex.com/sourcecontrol/changeset/view/37298?projectName=mvcturbine#758440)。

0
为什么不在Filter构造函数内使用静态工厂方法获取IRepository对象呢?你可以以一种允许DI发挥作用的方式使用工厂方法。
这样,DI将会在你的“网关”方法上发挥作用,而不是采用标准的“构造函数参数”方法。

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