タイトルの質問に飛び込む前に、バックアップして範囲を広げる必要があるかもしれません...
現在、ASP.NET MVC 1.0でWebアプリを作成しています(ただし、PCにはMVC 2.0がインストールされているため、1.0に厳密に制限されているわけではありません)-標準のMVCプロジェクトから始めました。基本的な「ASP.NETMVCへようこそ」で、右上隅に[ホーム]タブと[バージョン情報]タブの両方が表示されます。かなり標準的ですよね?
4つの新しいコントローラークラスを追加しました。それらを「天文学者」、「生物学者」、「化学者」、「物理学者」と呼びましょう。新しい各コントローラークラスには、[Authorize]属性が付加されています。
たとえば、BioologistController.csの場合
[Authorize(Roles = "Biologist,Admin")]
public class BiologistController : Controller
{
public ActionResult Index() { return View(); }
}
これらの[承認]タグは、役割に応じて異なるコントローラーにアクセスできるユーザーを自然に制限しますが、ユーザーが属している役割に基づいて、Site.MasterページのWebサイトの上部にメニューを動的に作成したいと思います。したがって、たとえば、「JoeUser」がロール「Astronomer」および「Physicist」のメンバーである場合、ナビゲーションメニューには次のように表示されます。
[ホーム][天文学者][物理学者][概要]
そして当然、「生物学者」または「化学者」コントローラーのインデックスページへのリンクはリストされません。
または、「JohnAdmin」がロール「Admin」のメンバーである場合、4つのコントローラーすべてへのリンクがナビゲーションバーに表示されます。
わかりました、あなたはその考えを大いに理解します...今本当の質問のために...
ASP.NETでの動的メニューの構築に関するこのStackOverflowトピックからの回答から始めて、これを完全に実装する方法を理解しようとしています。(私は初心者で、もう少しガイダンスが必要なので、私と一緒に裸にしてください。)
答えは、Controllerクラス(「ExtController」と呼びます)を拡張してから、新しいWhateverControllerをExtControllerから継承することを提案しています。
私の結論は、このExtControllerコンストラクターでReflectionを使用して、ロールを決定するために[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
}
}
}
これは実行可能ですか?その場合、ExtControllerコンストラクターでReflectionを実行して、[Authorize]属性と関連するロール(存在する場合)を検出するにはどうすればよいですか。
また!この質問の範囲を超えて、この「役割に基づく動的Site.Masterメニュー」の問題を解決する別の方法を提案してください。私はこれが最善のアプローチではないかもしれないことを認める最初の人です。
編集
たくさん読んで実験した後、私は自分自身の解決策を思いつきました。私の答えは以下を参照してください。建設的なフィードバック/批評は大歓迎です!