我正在为我的应用程序编写一个帮助程序,它为给定的强类型控制器/操作写出一个菜单项,如下所示:
<%= Html.MenuLink<WhateverController>(c => c.WhateverAction(), "Whatever") %>
作为此过程的一部分,如果当前页面和链接的页面相同,我想将active
类应用于输出的链接。我认为最好的方法是将当前请求的RouteValueDictionary
的内容与给予辅助方法的表达式的结果进行比较。但是,我无法找出比较两个RouteValueDictionary
中的项目是否相同的好方法。
有一种简单的方法吗?我有效地希望以下列方式完成它:
public static string MenuLink<T>(this HtmlHelper html, Expression<Action<T>> action, string linkText) where T : Controller
{
// var link = html.ActionLink<T>(action, linkText, new {}); // Not important yet
var routeValues = Microsoft.Web.Mvc.Internal.ExpressionHelper.GetRouteValuesFromExpression<T>(action); // Might change?
var currentRouteVals = html.ViewContext.RouteData.Values;
bool isActivePage = /* are the contents of routeValues also
inside currentRouteValues? */
var tb = new TagBuilder("li");
// Continues...
}
我尝试使用内置比较(==),但似乎它使用默认的相等实现,因此返回false,因为它们不是同一个实例。我也尝试了以下内容:
bool isActivePage = routeValues.All(x => currentRouteVals.ContainsValue(x));
但这也不起作用。我完全咆哮了错误的树吗?
答案 0 :(得分:3)
Bah,我发布问题,然后找出答案。我发布在这里以防其他任何人面临这个问题。我需要的一行如下:
bool isActivePage = routeValues.All(x => x.Value.ToString() == (currentRouteVals[x.Key].ToString()));
原来它最初将它们作为对象进行比较,而不是作为字符串。将它们转换为字符串可以按照人们的意愿进行比较,现在一切都很顺利。
应该注意的是,它们应该以这种方式进行比较。如果它们以相反的方式进行比较,则RouteValueDictionary可能包含除您关注的内容之外的其他内容(例如“id”值)。或者至少我就是这样理解的。进一步的实验可能需要我重新审视这个......
答案 1 :(得分:2)
我刚刚遇到同样的问题并且正在查看已接受的答案,并注意到它会:
此解决方案将提到的问题作为RouteValueDictionary的自包含扩展方法解决:
public static bool AreEqual(this RouteValueDictionary rvdA, RouteValueDictionary rvdB)
{
var Equal =
new Func<RouteValueDictionary, RouteValueDictionary, bool>((a, b) => a.All(kvp =>
{
object val = b[kvp.Key];
return val != null && kvp.Value.ToString().Equals(val.ToString(), StringComparison.InvariantCultureIgnoreCase);
}));
return rvdA.Count == rvdB.Count && Equal(rvdA, rvdB) && Equal(rvdB, rvdA);
}