1

カスタムViewEngineがあり、要求されたアクションにAuthorize属性フィルターがあるかどうかに応じて、使用されるマスターページを変更したいと思います。

これまでのところ、私は次のようなリフレクションを使用しています。

var method = controllerContext.Controller.GetType().GetMethod(viewName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase);
if (method != null)
{
    if (method.GetCustomAttributes(typeof(AuthorizeAttribute), true).Length > 0)
    {
        masterName = "Admin.master";
    }
}

しかし、私は反復的なタスクにリフレクションを使用することの大ファンではありません。ビューキャッシュを使用して最初から処理を高速化できることは知っていますが、 ?のFindViewメソッド内のアクションに適用されたフィルターのリストにアクセスするためのより直接的な方法があるかどうか疑問に思っています。ViewEngine

4

1 に答える 1

1

MVCアクションメソッドを含むものに関係なく、リフレクションを使用して属性情報を取得することにほとんど制限されています。;)

この情報を取得するための他の唯一の手法は、ControllerDescriptor 経路を経由することです。

あなたの場合、authorize 属性の検索をまったくスキップして、ユーザーが承認されているかどうかを尋ねて、必要なマスター ページを提供することができます。

以前にカスタム ビュー エンジンでマスター ページを動的に設定したことがあり、最もパフォーマンスの高いオプションは、利用可能な HttpContextBase 情報を確認することです。あるシナリオでは、必要に応じてクエリ パラメーターを渡したり、{masterPage} ルート パラメーターに追加したりしました。

アクション情報への唯一の他の経路は、ReflectedControllerDescriptor ルートです。この方法の問題点は、非常に冗長であり、実行するために多くのコード行が必要になることです。

これは、セキュリティ リンクのプルーニング トリミングを行う「記述子」手法のコードの一部です (stackoverflow で見つけました!)。このコードは、カスタム ビュー エンジンにある場合、マスターページを動的に設定するためにも使用できます。それはあなたが探しているものではありませんが、他の誰かが別の場所で同じ動的マスターページ設定を達成するのに役立つかもしれません:

    public static bool HasActionPermission( this HtmlHelper htmlHelper, string actionName, string controllerName )
    {
        //if the controller name is empty the ASP.NET convention is:
        //"we are linking to a different controller
        ControllerBase controllerToLinkTo = string.IsNullOrEmpty(controllerName) 
                                                ? htmlHelper.ViewContext.Controller
                                                : GetControllerByName(htmlHelper, controllerName);

        var controllerContext = new ControllerContext(htmlHelper.ViewContext.RequestContext, controllerToLinkTo);

        var controllerDescriptor = new ReflectedControllerDescriptor(controllerToLinkTo.GetType());

        var actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName);

        return ActionIsAuthorized(controllerContext, actionDescriptor);
    }


    private static bool ActionIsAuthorized(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
    {
        if (actionDescriptor == null)
            return false; // action does not exist so say yes - should we authorise this?!

        AuthorizationContext authContext = new AuthorizationContext(controllerContext);

        // run each auth filter until on fails
        // performance could be improved by some caching
        foreach (IAuthorizationFilter authFilter in actionDescriptor.GetFilters().AuthorizationFilters)
        {
            authFilter.OnAuthorization(authContext);

            if (authContext.Result != null)
                return false;
        }

        return true;
    }
于 2009-11-02T14:38:49.377 に答える