我正在 mvc4 中建立一个新网站,我正在从数据库中检索菜单动态。为了防止在每个控制器和视图中一遍又一遍地执行相同的操作来创建菜单,我正在使用带有部分视图的部分控制器来构建菜单。多亏了这篇文章,我才做到了这一点。
我想要实现的下一件事是根据当前控制器和操作确定当前活动的菜单项,因此我创建了一个 html 助手来执行此操作。代码基于这篇文章。
我的代码如下所示;
部分控制器.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);
}
主菜单.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函数来做,但我不知道这是否可能或如何做?