Vielleicht sollte ich sichern und den Anwendungsbereich erweitern, bevor Sie in die Titelfrage eintauchen ...ASP.NET MVC: Wie finden Sie Controller mit [Authorize] -Attributen mithilfe von Reflection in C#? (oder Wie man Dynamic Site.Master Menüs erstellt?)
Ich schreibe gerade eine Webanwendung in ASP.NET MVC 1.0 (obwohl ich MVC 2.0 auf meinem PC installiert habe, also bin ich nicht genau auf 1.0 beschränkt) - Ich habe mit dem Standard MVC - Projekt begonnen, das Ihre grundlegende "Willkommen bei ASP.NET MVC" hat und beide zeigt Registerkarte [Home] und [Info] in der oberen rechten Ecke. Ziemlich Standard, oder?
Ich habe 4 neue Controller-Klassen hinzugefügt, nennen wir sie "Astronomen", "Biologen", "Chemiker" und "Physiker". An jede neue Controller-Klasse ist das [Authorize] -Attribut angehängt.
Zum Beispiel für die BiologistController.cs
[Authorize(Roles = "Biologist,Admin")]
public class BiologistController : Controller
{
public ActionResult Index() { return View(); }
}
Diese [autorisieren] Tags natürlich begrenzen, welcher Benutzer auf Rollen je verschiedene Controller zugreifen können, aber ich möchte ein Menü am oberen Rand meiner Website dynamisch bauen in der Site.Master-Seite basierend auf den Rollen, zu denen der Benutzer gehört. So zum Beispiel, wenn "JoeUser" war ein Mitglied der Rollen "Astronom" und "Physiker", würde das Navigationsmenü sagen:
[Home] [Astronom] [Physikerin] [über]
Und natürlich würde es nicht Links zu "Biologe" oder "Chemiker" Controller-Index-Seite.
Oder wenn "JohnAdmin" ein Mitglied der Rolle "Admin" war, würden Links zu allen 4 Controllern in der Navigationsleiste erscheinen.
Ok, erhalten Sie prolly die Idee ... Jetzt für die eigentliche Frage ...
mit the answer from this StackOverflow topic about Dynamic Menu building in ASP.NET starten, ich versuche zu verstehen, wie ich dies in vollem Umfang umsetzen würde. (Ich bin ein Neuling und brauche ein wenig mehr Anleitung, also bitte bare mit mir.)
Die Antwort schlägt vor, die Controller-Klasse erweitern (nennen Sie es "ExtController") und dann jede neue WhattingController erben von ExtController.
Meine Schlussfolgerung ist, dass ich Reflection in diesem ExtController-Konstruktor verwenden müsste, um zu ermitteln, welche Klassen und Methoden [Authorize] -Attribute an sie angehängt haben, um die Rollen zu bestimmen. Speichern Sie dann mit einem Static Dictionary die Rollen und Controller/Methoden in Schlüssel/Wert-Paaren.
stelle ich mir das so etwas wie:
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
}
}
}
Ist das machbar? Wenn ja, wie führe ich Reflection im ExtController-Konstruktor aus, um das [Authorize] -Attribut und die zugehörigen Rollen (falls vorhanden) zu finden
AUCH! Fühlen Sie sich frei, bei dieser Frage nicht in den Geltungsbereich zu kommen und schlagen Sie eine alternative Lösung vor, um dieses "Dynamic Site.Master Menu basierend auf Rollen" -Problem zu lösen. Ich bin der Erste, der zugibt, dass dies nicht der beste Ansatz ist.
EDIT
Nach viel Lesen und Experimentieren, kam ich mit meiner eigenen Lösung auf. Siehe unten für meine Antwort. Jede konstruktive Rückmeldung/Kritik erwünscht!
Als Hinweis wäre es wahrscheinlich besser, in ApplicationStart ein Dictionary zu erstellen, da sich die Klassen erst bei der erneuten Implementierung ändern. Dann ist das Erstellen des Menüs nicht immer dynamisch, sondern eine schnelle Suche in einem Wörterbuch. –