2009-11-10 102 views
2

我寫我的應用程序的輔助,其寫出一個菜單項,對於給定的強類型的控制器/動作如下:比較兩個RouteValueDictionary實例

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

但這也行不通。我完全吠叫錯了樹嗎?

回答

3

Bah,我張貼問題,然後找出答案。在這裏張貼,以防其他人面臨這個問題。我需要的行如下:

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

原來,它最初是比較它們作爲對象,而不是字符串。將它們轉換爲字符串會比較它們,正如人們希望的那樣,現在一切都很好。

應該指出,他們應該圍繞這種方式進行比較。如果通過其他方式進行比較,則RouteValueDictionary可能包含您關心的其他內容(例如「id」值)。或者至少這是我目前的理解。進一步的實驗可能需要我重新審視這個...

2

我只是遇到同樣的問題,並期待在接受的答案,發現它會:

  • 原因的異常,如果該鍵沒有在存在第二個路由值列表
  • 區分大小寫,對於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); 
}