比较两个RouteValueDictionary实例

时间:2009-11-10 21:18:26

标签: asp.net-mvc asp.net-mvc-routing

我正在为我的应用程序编写一个帮助程序,它为给定的强类型控制器/操作写出一个菜单项,如下所示:

<%= 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));

但这也不起作用。我完全咆哮了错误的树吗?

2 个答案:

答案 0 :(得分:3)

Bah,我发布问题,然后找出答案。我发布在这里以防其他任何人面临这个问题。我需要的一行如下:

bool isActivePage = routeValues.All(x => x.Value.ToString() == (currentRouteVals[x.Key].ToString()));

原来它最初将它们作为对象进行比较,而不是作为字符串。将它们转换为字符串可以按照人们的意愿进行比较,现在一切都很顺利。

应该注意的是,它们应该以这种方式进行比较。如果它们以相反的方式进行比较,则RouteValueDictionary可能包含除您关注的内容之外的其他内容(例如“id”值)。或者至少我就是这样理解的。进一步的实验可能需要我重新审视这个......

答案 1 :(得分:2)

我刚刚遇到同样的问题并且正在查看已接受的答案,并注意到它会:

  • 如果第二个routeValues列表中不存在该键,则会导致异常
  • 区分大小写,通常不是Microsoft URI的情况。
  • 如果密钥位于第二个列表但不是第一个列表,则列表将比较为不正确的列表。

此解决方案将提到的问题作为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);
}