Мы используем пользовательский AuthorizeAttribute
для обработки нескольких аспектов авторизации пользователя. Мне нужно добавить доступ к базе данных, чтобы проверить значение во время авторизации. Этот проект использует шаблон репозитория, и все репозитории создаются в конструкторах контроллера через StructureMap.Узел установки не работает с StructureMap в ASP.NET MVC авторизационный фильтр
К сожалению, похоже, что использовать инжектор конструктора с фильтрами невозможно. Я нашел статью Джимми Богарда (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; }
Когда я запускаю проект и получить доступ к защищенной странице, й e AuthorizeCore
код попадает дважды. В первый раз мое свойство настроено и работает правильно. Тем не менее, второй вызов завершается с ошибкой, так как свойство имеет значение. Я установил точку останова в методе 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 заботитесь поделиться мудростью ? Заранее благодарю за любую помощь!
Edit: Вот код для файла _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, я выделил проблему на вызов меню кэндо. Если я положу точку останова на конечной строке _Menu.cshtml
и сделаю шаг, я вижу, что DoGetInstance вызвал мой HomeController. Как только это будет завершено, OnAuthorization будет запущена во второй раз, и мое свойство repo будет null.
Кто-нибудь знает, что мне здесь не хватает?
Я не думаю, что вы найдете ответ, если вы не можете объяснить, почему ваш атрибут авторизированным вызывается дважды, и кто создавая его второй раз. Вызывается метод GetFilters дважды? – NightOwl888
Извините, второй вызов происходит от рендеринга частичного имени _Menu.cshtml внутри моего файла _Layout.cshtml (это можно увидеть в столах вызовов). –
И нет, GetFilters вызывается только один раз (как указано выше). Кажется, что класс кэшируется, но кешированная версия хранится до того, как произошла сборка? Я не знаю. –