我们使用自定义AuthorizeAttribute
来处理用户授权的几个方面。我需要添加对数据库的访问权限以在授权期间检查值。该项目使用 Repository 模式,并且 Repos 都通过 StructureMap 在控制器构造函数中实例化。
不幸的是,似乎没有办法将构造函数注入与过滤器一起使用。我找到了 Jimmy Bogard 的一篇文章(http://lostechies.com/jimmybogard/2010/05/03/dependency-injection-in-asp-net-mvc-filters/),解释了如何使用属性注入来处理这种情况。基本上,Jimmy 的代码会拦截其中的GetFilters
方法ControllerActionInvoker
并BuildUp
在每个过滤器上运行以填充属性。这正是我所需要的,所以我添加了以下课程 -
public class InjectingActionInvoker : ControllerActionInvoker
{
private readonly IContainer _container;
public InjectingActionInvoker(IContainer container)
{
_container = container;
}
protected override FilterInfo GetFilters(
ControllerContext controllerContext,
ActionDescriptor actionDescriptor)
{
var info = base.GetFilters(controllerContext, actionDescriptor);
info.AuthorizationFilters.ForEach(_container.BuildUp);
info.ActionFilters.ForEach(_container.BuildUp);
info.ResultFilters.ForEach(_container.BuildUp);
info.ExceptionFilters.ForEach(_container.BuildUp);
return info;
}
}
然后用这些线将它连接到 StructureMap -
For<IActionInvoker>().Use<InjectingActionInvoker>();
For<ITempDataProvider>().Use<SessionStateTempDataProvider>();
Policies.SetAllProperties(c =>
{
c.OfType<IActionInvoker>();
c.OfType<ITempDataProvider>();
c.WithAnyTypeFromNamespaceContainingType<UserProfileRepository>();
});
最后,我将公共属性添加到我的自定义AuthorizeAttribute
类中 -
[SetterProperty]
public UserProfileRepository User { get; set; }
当我运行项目并访问安全页面时,AuthorizeCore
代码被命中两次。第一次,我的财产已设置并正常工作。但是,第二次调用失败,因为属性为 null。我在方法中设置了一个断点GetFilters
,它只是第一次被击中。不幸的是,我只是对 StructureMap 或 Filters 的理解不够深入,无法确切地知道它的横向发展。
以下是调用堆栈,以防对任何人有用 -
呼叫#1
AppName.dll!AppName.Filters.SiteAuthorizeAttribute.AuthorizeCore(System.Web.HttpContextBase httpContext) Line 78 C#
[External Code]
AppName.dll!AppName.Filters.SiteAuthorizeAttribute.OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext) Line 31 C#
[External Code]
呼叫#2
AppName.dll!AppName.Filters.SiteAuthorizeAttribute.AuthorizeCore(System.Web.HttpContextBase httpContext) Line 69 C#
[External Code]
AppName.dll!AppName.Filters.SiteAuthorizeAttribute.OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext) Line 31 C#
[External Code]
App_Web_1fnmflat.dll!ASP._Page_Views_Shared__Menu_cshtml.Execute() Line 2 C#
[External Code]
App_Web_1fnmflat.dll!ASP._Page_Views_Shared__Layout_cshtml.Execute() Line 51 C#
[External Code]
任何 StructureMap 大师愿意分享一些智慧吗?提前感谢您的帮助!
编辑:这是_Menu.cshtml
文件的代码 -
@(Html.Kendo().Menu()
.Name("Menu")
.Items(items =>
{
items.Add().Text("My Dashboard").Action("Dashboard", "Home");
items.Add().Text("My Account").Action("Edit", "Account");
items.Add().Text("Purchase/Renew").Action("Index", "Purchase");
items.Add().Text("Administration")
.Items(children =>
{
children.Add().Text("Accounts").Action("Index", "UserProfile");
children.Add().Text("Coupons").Action("Index", "Coupon");
});
items.Add().Text("Logout").Action("Logout", "Logon");
})
)
感谢 NightOwl888 的一些提示,我已将问题隔离到 Kendo Menu 调用。如果我在最后一行设置断点_Menu.cshtml
并进入,我会看到为我的 HomeController 调用了 DoGetInstance。一旦完成,第二次触发 OnAuthorization 并且我的 repo 属性为空。
有人知道我在这里缺少什么吗?