C#mvc从部分控制器获取带有菜单项的活动菜单项

时间:2013-07-17 20:30:42

标签: c# asp.net-mvc asp.net-mvc-4 html-helper

我正在mvc4中构建一个新网站,我正在从数据库中检索菜单动态。为了防止在每个控制器和视图中反复执行相同的操作以创建菜单,我使用具有局部视图的部分控制器来构建菜单。我已经这样做了,感谢this文章。

我想要实现的下一步是根据当前控制器和操作确定当前活动菜单项,因此我创建了一个html帮助程序来执行此操作。该代码基于this article

我的代码看起来像这样;

Partialcontroller.cs

[ChildActionOnly]
        public ActionResult MainMenu()
        {
            var viewModel = new MenuModel();

            try
            {
                IList<MenuItem> menuItems = MenuService.First(x => x.Name == "MainMenu").MenuItems;

                //Get the menuItems collection from somewhere
                if (menuItems != null && menuItems.Count > 0)
                {
                    viewModel.MenuItems = menuItems;
                    return View(viewModel);
                }
            }
            catch (Exception exception)
            {
                //TODO: Exception handling and logging
            }

            return View(viewModel);
        }

MainMenu.cshtml

这是布局中包含的局部视图,其中包含这段代码;

<nav class="nav-collapse collapse">
    <ul class="row-fluid nav">
        @foreach (var item in Model.MenuItems)
        {
            <li class="span2">
                @Html.MenuItem(item.Name, item.ActionName, item.ControllerName)
            </li>
        }

    </ul>
</nav>

HtmlHelper.cs

我在部分视图中使用htmlhelper方法来构建菜单项。这是问题所在。

public static MvcHtmlString MenuItem(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName)
        {
            string currentAction = htmlHelper.ViewContext.RouteData.GetRequiredString("action");
            string currentController = htmlHelper.ViewContext.RouteData.GetRequiredString("controller");
            if (actionName == currentAction && controllerName == currentController)
            {
                return htmlHelper.ActionLink(
                    linkText,
                    actionName,
                    controllerName,
                    null,
                    new
                    {
                        @class = "active"
                    });
            }

            //var link = htmlHelper.ActionLink("<span>{LinkText}<span>", actionName, controllerName).ToHtmlString();
            //return new MvcHtmlString(link.Replace("{LinkText}", linkText));

            return htmlHelper.ActionLink(linkText, actionName, controllerName);
        }

调试时我发现变量'currentController'包含值'Partial'而变量'currentAction'包含'MainMenu'。所有这些对我来说都很合乎逻辑,因为这是用于构建菜单的控制器操作。 但是,这也是问题所在。这两个变量将始终包含值'Partial'和'MainMenu',因为MenuItem助手总是在由PartialController实例化的视图中调用。这样我就永远无法匹配发出请求的实际控制器。

我想要做的就是,例如,单击菜单中的联系人按钮,将其视为活动菜单项。此菜单项的操作可以是ContactController的Index操作,因此如果控制器和操作与控制器匹配以及与菜单项映射的操作,则应添加额外的css类。

我该怎么做才能解决这个问题?我更喜欢在代码中而不是脏javascript函数中执行此操作,但我不知道它是否可行或如何执行?

1 个答案:

答案 0 :(得分:6)

我认为您可以使用htmlHelper.ViewContext上的ParentActionViewContext属性访问父控制器

string currentController = htmlHelper.ViewContext.ParentActionViewContext.RouteData.GetRequiredString("controller");