3

HtmlHelperの拡張メソッドを作成しました(アクティブなメニュー項目-asp.net mvc3マスターページから派生)。これにより、現在のページのcssclass「アクティブ」を出力できます。

ただし、エリアを使用するようにリファクタリングしたため、ホームと呼ばれるコントローラーとインデックスと呼ばれるアクションがいくつかのエリアにあるため、このメソッドは機能しなくなりました。そのため、routevalues匿名タイプの一部として渡されたAreaを使用して現在のエリアをチェックすることにより、これを整理しようとしています。

したがって、私の拡張メソッドは次のようになります。

public static MvcHtmlString NavigationLink<T>(this HtmlHelper<T> htmlHelper, string linkText, string actionName, string controllerName, dynamic routeValues)
{
    string currentController = htmlHelper.ViewContext.RouteData.GetRequiredString("controller");
    string currentArea = htmlHelper.ViewContext.RouteData.DataTokens["Area"] as string;
    if (controllerName == currentController && IsInCurrentArea(routeValues,currentArea))
    {
        return htmlHelper.ActionLink(
            linkText,
            actionName,
            controllerName,
            (object)routeValues,
            new
            {
                @class = "active"
            });
    }
    return htmlHelper.ActionLink(linkText, actionName, controllerName, (object)routeValues, null);
}

private static bool IsInCurrentArea(dynamic routeValues, string currentArea)
{
    string area = routeValues.Area; //This line throws a RuntimeBinderException
    return string.IsNullOrEmpty(currentArea) && (routeValues == null || area == currentArea);
}

次の行をコンパイルできるように、routeValuesのタイプを動的に変更しました。

文字列領域=routeValues.Area;

デバッガーのrouteValuesオブジェクトのAreaプロパティを確認できますが、アクセスするとすぐにRuntimeBinderExceptionが発生します。

匿名タイプのプロパティにアクセスするためのより良い方法はありますか?

4

1 に答える 1

2

RouteValueDictionaryのコンストラクターを使用して、Areaプロパティを簡単に検索できることがわかりました。

また、コントローラーの値も使用しようとして問題が複雑になっていることに気付いたため、コードは次のようになりました。

    public static MvcHtmlString NavigationLink<T>(this HtmlHelper<T> htmlHelper, string linkText, string actionName, string controllerName, object routeValues)
    {
        string currentArea = htmlHelper.ViewContext.RouteData.DataTokens["Area"] as string;

        if (IsInCurrentArea(routeValues, currentArea))
        {
            return htmlHelper.ActionLink(
                linkText,
                actionName,
                controllerName,
                routeValues,
                new
                {
                    @class = "active"
                });
        }
        return htmlHelper.ActionLink(linkText, actionName, controllerName, routeValues, null);
    }

    private static bool IsInCurrentArea(object routeValues, string currentArea)
    {
        if (routeValues == null)
            return true;

        var rvd = new RouteValueDictionary(routeValues);
        string area = rvd["Area"] as string ?? rvd["area"] as string;
        return area == currentArea;
    }
于 2011-02-15T21:35:18.010 に答える