Может быть, мне стоит сделать резервную копию и расширить рамки, прежде чем углубляться в вопрос, связанный с заголовком ...
В настоящее время я пишу веб-приложение на ASP.NET MVC 1.0 (хотя на моем компьютере установлен MVC 2.0, поэтому я не ограничен только 1.0). Я начал со стандартного проекта MVC, в котором есть ваш basic Добро пожаловать в ASP.NET MVC, и в правом верхнем углу отображаются вкладки [Главная] и [О программе]. Довольно стандартно, правда?
Я добавил 4 новых класса Контроллеров, назовем их Астроном, Биолог, Химик и Физик. К каждому новому классу контроллера прикреплен атрибут [Authorize].
Например, для файла BiologistController.cs
[Authorize(Roles = "Biologist,Admin")]
public class BiologistController : Controller
{
public ActionResult Index() { return View(); }
}
Эти теги [Authorize], естественно, ограничивают, какой пользователь может получить доступ к различным контроллерам в зависимости от ролей, но я хочу динамически создавать меню в верхней части моего веб-сайта на странице Site.Master на основе ролей, частью которых является пользователь. Так, например, если JoeUser был членом группы Roles Astronomer and Physicist, в меню навигации было бы написано:
[На главную] [Астроном] [Физик] [О себе]
И, естественно, он не перечисляет ссылки на страницу указателя контроллера биолога или химика.
Или, если бы JohnAdmin был членом Role Admin, ссылки на все 4 контроллера отобразились бы на панели навигации.
Хорошо, вы, наверное, поняли ... А теперь настоящий вопрос ...
Начиная с ответа из этой темы StackOverflow о создании динамического меню в ASP.NET, я пытаюсь понять, как я смогу полностью реализовать это. (Я новичок и нуждаюсь в дополнительных советах, так что, пожалуйста, обнажитесь со мной.)
В ответе предлагается расширить класс контроллера (назовите его ExtController), а затем унаследовать каждый новый контроллер WhateverController от ExtController.
Я пришел к выводу, что мне нужно использовать Reflection в этом конструкторе ExtController, чтобы определить, к каким классам и методам прикреплены атрибуты [Authorize] для определения ролей. Затем, используя статический словарь, сохраните роли и контроллеры / методы в парах ключ-значение.
Я себе это представляю примерно так:
public class ExtController : Controller
{
protected static Dictionary<Type,List<string>> ControllerRolesDictionary;
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
// build list of menu items based on user's permissions, and add it to ViewData
IEnumerable<MenuItem> menu = BuildMenu();
ViewData["Menu"] = menu;
}
private IEnumerable<MenuItem> BuildMenu()
{
// Code to build a menu
SomeRoleProvider rp = new SomeRoleProvider();
foreach (var role in rp.GetRolesForUser(HttpContext.User.Identity.Name))
{
}
}
public ExtController()
{
// Use this.GetType() to determine if this Controller is already in the Dictionary
if (!ControllerRolesDictionary.ContainsKey(this.GetType()))
{
// If not, use Reflection to add List of Roles to Dictionary
// associating with Controller
}
}
}
Это выполнимо? Если да, то как мне выполнить Reflection в конструкторе ExtController, чтобы обнаружить атрибут [Authorize] и связанные роли (если есть)
ТАКЖЕ! Не стесняйтесь выходить за рамки этого вопроса и предлагать альтернативный способ решения этого динамического меню Site.Master на основе проблемы ролей. Я первый, кто признает, что это, возможно, не лучший подход.
ИЗМЕНИТЬ
После долгого чтения и экспериментов я пришел к собственному решению. Мой ответ смотрите ниже. Любые конструктивные отзывы / критика приветствуются!