2010-10-17 152 views
29

我有幾個路由在我的Global.asax中定義;如何從RouteData獲取路由名稱?

當我在一個頁面上時,我需要弄清楚當前路由的路由名稱是什麼,因爲路由名稱驅動我的站點菜單。

這怎麼辦?

回答

20

不幸的是,無法獲取路由的路由名稱,因爲該名稱不是路由的屬性。將路由添加到RouteTable時,該名稱將用作路由的內部索引,並且從不公開。

有一種方法可以做到這一點。

當您註冊路由時,請在具有路由名稱的路由上設置DataToken並使用它來過濾路由。

執行#1最簡單的方法是編寫自己的擴展方法來映射路由。

+2

mvc 4也許? :-) – 2010-12-19 09:14:48

+0

@Simon_Weaver名稱仍然不是MVC中的屬性4 – 2014-04-09 01:05:59

+2

仍然不是MVC 5中的Route屬性! – Triynko 2016-10-06 05:43:31

1

我一直面臨着同樣的困境,我得出的結論是,不幸的是,似乎沒有辦法找出ASP.NET選擇使用哪條路徑(通過其名稱)。

看來你只能通過你的路線中可能存在的參數的名字來確定 - 這些將顯示在RouteData.Values字典中。

如果有人知道某種方式來獲取由ASP.NET爲給定的URL選擇的路由的實際名稱,我也有興趣知道如何自己做到這一點!

+0

是的,那太臭了!他們有一個包含名稱和路線的私人地圖,但是沒有辦法公開它:( – Andrey 2010-10-18 00:01:11

+0

其實,Haacked的解決方案效果很好,現在在我的製作網站:) – Andrey 2010-12-19 16:46:08

+0

@Andrey:是的,但這是一個駭人聽聞的問題: - ),我真的更喜歡一個「正確的」版本,而不必自己設置DataTokens - 只是爲了獲取路由的名稱...... – 2010-12-19 18:27:43

8

如果你與你需要檢查(特殊情況或兩個)的重要途徑一小部分工作,你可以只是這樣做:

if (routeData.Route == RouteTable.Routes["gallery-route"]) 
{ 
    // current route is 'gallery-route' 
} 

爲按需路由名稱的常見原因是用於調試目的。一個快速和骯髒的方式來做到這一點 - 但你需要將每個路由名稱添加到名稱數組。應該適用於調試 - 特別是如果代碼在生產過程中沒有運行。

// quick and dirty way to get route name 
public string GetRouteName(RouteData routeData) 
{ 
    foreach (string name in new [] { "gallery-route", 
            "products-route", 
            "affiliate-route", 
            "default" }) 
    { 
     if (routeData.Route == RouteTable.Routes[name]) 
     { 
      return name; 
     } 
    } 
    return "UNKNOWN-ROUTE"; // or throw exception 
} 

對於超出此範圍的任何事情,您應該採取@ haacked解決方案所需的(最小)時間。

+0

感謝您的提示。你的第一個想法對我來說非常出色,因爲我只需要在文章頁面查看他們是通過標題路線還是通過了rowid路線。 CheerZ! – eidylon 2010-12-23 20:01:31

+0

感謝哥們,它也適合我。 – Devsainii 2013-05-30 10:34:56

7

下面是@ haacked的建議的實現 - 還有一個簡單的'剃鬚刀'表來顯示路徑數據。

注意:您可能沒有意識到所有標準的'MapRoute'方法實際上都是擴展方法。因此我們不能使用相同的名稱。我剛剛稱之爲'MapRoute2',因爲現在就是我所能想到的。

您必須更換所有呼叫到MapRoute2調用圖路線,不要忘了所有AreaRegistration文件以及的global.asax.cs

擴展方法:

public static class RouteNameExtensions 
{ 
    // RouteCollection 
    public static Route MapRoute2(this RouteCollection routes, string name, string url) 
    { 
     return AddRouteNameDataToken(name, routes.MapRoute(name, url)); 
    } 

    public static Route MapRoute2(this RouteCollection routes, string name, string url, object defaults) 
    { 
     return AddRouteNameDataToken(name, routes.MapRoute(name, url, defaults)); 
    } 

    public static Route MapRoute2(this RouteCollection routes, string name, string url, string[] namespaces) 
    { 
     return AddRouteNameDataToken(name, routes.MapRoute(name, url, namespaces)); 
    } 

    public static Route MapRoute2(this RouteCollection routes, string name, string url, object defaults, object constraints) 
    { 
     return AddRouteNameDataToken(name, routes.MapRoute(name, url, defaults, constraints)); 
    } 

    public static Route MapRoute2(this RouteCollection routes, string name, string url, object defaults, string[] namespaces) 
    { 
     return AddRouteNameDataToken(name, routes.MapRoute(name, url, defaults, namespaces)); 
    } 

    public static Route MapRoute2(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces) 
    { 
     return AddRouteNameDataToken(name, routes.MapRoute(name, url, defaults, constraints, namespaces)); 
    } 

    // AreaRegistrationContext 
    public static Route MapRoute2(this AreaRegistrationContext routes, string name, string url) 
    { 
     return AddRouteNameDataToken(name, routes.MapRoute(name, url)); 
    } 

    public static Route MapRoute2(this AreaRegistrationContext routes, string name, string url, object defaults) 
    { 
     return AddRouteNameDataToken(name, routes.MapRoute(name, url, defaults)); 
    } 

    public static Route MapRoute2(this AreaRegistrationContext routes, string name, string url, string[] namespaces) 
    { 
     return AddRouteNameDataToken(name, routes.MapRoute(name, url, namespaces)); 
    } 

    public static Route MapRoute2(this AreaRegistrationContext routes, string name, string url, object defaults, object constraints) 
    { 
     return AddRouteNameDataToken(name, routes.MapRoute(name, url, defaults, constraints)); 
    } 

    public static Route MapRoute2(this AreaRegistrationContext routes, string name, string url, object defaults, string[] namespaces) 
    { 
     return AddRouteNameDataToken(name, routes.MapRoute(name, url, defaults, namespaces)); 
    } 

    public static Route MapRoute2(this AreaRegistrationContext routes, string name, string url, object defaults, object constraints, string[] namespaces) 
    { 
     return AddRouteNameDataToken(name, routes.MapRoute(name, url, defaults, constraints, namespaces)); 
    } 

    private static Route AddRouteNameDataToken(string name, Route route) 
    { 
     route.DataTokens["route-name"] = name; 
     return route; 
    } 
} 

這是一個簡單的剃​​刀。我使用的顯示路由信息CSHTML文件:

<table class="basic-table"> 
    <tr> 
     <th>Route Key</th> 
     <th>Value</th> 
    </tr> 

    <tr> 
     <td><strong>Route name</strong></td> 
     <td>@ViewContext.RouteData.DataTokens["route-name"]</td> 
    </tr> 

    @foreach (var route in ViewContext.RouteData.Values) 
    { 
     <tr> 
      <td>- @route.Key</td> 
      <td>@(route.Value ?? "<null>")</td> 
     </tr> 
    } 
    @foreach (var route in ViewContext.RouteData.DataTokens.Where(x=>x.Key != "route-name")) 
    { 
     <tr> 
      <td><strong>@route.Key</strong></td> 
      <td>@(route.Value ?? "<null>")</td> 
     </tr> 
    } 

</table> 
+0

這幾乎是我在10月份當Haacked建議它的時候實現它的方法:)無論如何,謝謝你的提示 – Andrey 2010-12-19 16:45:00

+0

我想這是唯一的方法;-)它只是寫一些所有重載的痛苦 - 然後你意識到您需要爲區域 – 2010-12-19 20:20:40

6

我會贊成票Simon_Weaver的答案,但不幸的是我剛剛加入,並沒有信譽點這樣做。

添加到他的答案,因爲這正是我一直在尋找,這是我做的方式:

我有一個公共枚舉「PageRouteTable」:

public enum PageRouteTable 
{ 
    // -- User Area 
    UserArea_Locations, 
    UserArea_Default, 
    UserArea_PasswordReset, 
    UserArea_Settings, 
    . 
    . 
    . 
} 

我用這個枚舉建立路由時:

/* -- User Area Routes -- */ 
routes.MapPageRoute(PageRouteTable.UserArea_Default.ToString(), "home", "~/UserArea/Default.aspx"); 

然後我創建了一個頁面擴展方法:

public static PageRouteTable? CurrentRoute(this Page p) 
{ 
    string[] pageRoutes = Enum.GetNames(typeof (PageRouteTable)); 
    foreach (string pageRoute in pageRoutes) 
    { 
     if (p.RouteData.Route == RouteTable.Routes[pageRoute]) 
     { 
      return (PageRouteTable)Enum.Parse(typeof (PageRouteTable), pageRoute); 
     } 
    } 
    return null; 
} 

現在,在我的網頁,我可以簡單地用一個開關對它採取行動:

PageRouteTable? currentRoute = this.CurrentRoute(); 
if (currentRoute.HasValue) { 
    switch(currentRoute.Value) { 
     case PageRouteTable.UserArea_Default: 
      // Act accordingly 
      break; 
     . 
     . 
     . 
    } 
} 

我也有明確定義的變量的利益而不必擔心對編碼字符串。這爲我節省了大量的維修麻煩。

- 開心編碼。

3

RouteCollection維護命名路線的私人字典。

路線名稱可以使用反射來獲取私有字段的查詢字典,其值是路由的項目的價值和

    1. 被誘導出來。

    下面的擴展方法遵循下列過程

    public static string Name(this RouteBase original) 
    { 
        var routes = System.Web.Routing.RouteTable.Routes; 
    
        if (routes.Contains(original)) 
        { 
         var namedMapField = routes.GetType().GetField("_namedMap", BindingFlags.NonPublic | BindingFlags.Instance); 
         var namedMap = namedMapField.GetValue(routes) as Dictionary<string, RouteBase>; 
    
         var query = 
          from pair in namedMap 
          where pair.Value == original 
          select pair.Key; 
    
         return query.Single(); 
        } 
    
        return string.Empty; 
    } 
    
  • 0

    ,我已經實現了一個簡單的方法是提供了.MapPageRoute方法的「默認」 PARAM名爲關鍵。使用常量作爲默認值,並且您可以像平常一樣將其從Page.RouteData.Values集合中取出。

    示例(vb.net)

    routes.MapPageRoute("league-division-stats", "{league}/{division}/stats", "~/routes/league-division-stats.aspx", False, New RouteValueDictionary(New With {.section = "stats"})) 
    

    Page.RouteData.Values("section")給我 '統計'

    9

    FWIW,由於由@Simon_Weaver所示的擴展和示例是基於MVC和後標記有的WebForms,我想我會分享我的基於WebForms的擴展方法:

    public static void MapPageRouteWithName(this RouteCollection routes, string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess = true, 
          RouteValueDictionary defaults = default(RouteValueDictionary), RouteValueDictionary constraints = default(RouteValueDictionary), RouteValueDictionary dataTokens = default(RouteValueDictionary)) 
        { 
         if (dataTokens == null) 
          dataTokens = new RouteValueDictionary(); 
    
         dataTokens.Add("route-name", routeName); 
         routes.MapPageRoute(routeName, routeUrl, physicalFile, checkPhysicalUrlAccess, defaults, constraints, dataTokens); 
        } 
    
        public static string GetRouteName(this RouteData routeData) 
        { 
         if (routeData.DataTokens["route-name"] != null) 
          return routeData.DataTokens["route-name"].ToString(); 
         else return String.Empty; 
        } 
    

    所以現在在Global.asax.cs中,當你註冊你的路由,而不是做這樣routes.MapPageRoute(...) - 改爲使用擴展方法並執行routes.MapPageRouteWithName(...)

    然後,當您想要檢查您的路線時,只需執行Page.RouteData.GetRouteName()

    就是這樣。沒有反射,並且對「路由名稱」的唯一硬編碼引用在兩個擴展方法中(如果您真的想用常量可以用const替換)。在你的方法,你需要的路線,那麼你可以撥打以下

     routeCollection.MapPageRoute("RouteForProduct", "Product/{ProductName}", "~/IRShop.aspx", false, new RouteValueDictionary { { "Section", "product" } }); 
         routeCollection.MapPageRoute("RouteForProductList", "ProductList/{CatName}", "~/IRShop.aspx", false, new RouteValueDictionary { { "Section", "productlist" } }); 
         routeCollection.MapPageRoute("RouteForContentList", "Content/{PageName}", "~/IRShop.aspx", false, new RouteValueDictionary { { "Section", "content" } }); 
    

    然後:

    var x = Page.RouteData.Values["Section"].ToString(); 
    

    ,你將有一個字符串

    +2

    +1加倍,謝謝您爲我節省了MVC - > WebForms翻譯練習。 – 2013-10-09 16:17:31

    2

    對於C#,你可以宣佈你的路線,像這樣設置在你的global.asax中,然後根據需要使用。

    1

    您可以添加每個路由參數以及它不是必需的這個參數,在您的網址: 你可以把你的路線名稱,這樣inGlobal.asax參數:

    routes.MapPageRoute("Page", 
           "Page-{ID}", 
           "~/Item_show.aspx", false, new RouteValueDictionary{ { "RouteName" , "Page" }}); 
    

    而在你的網頁訪問它:

    if (RouteData.Values["RouteName"] != null) 
          { 
           if (RouteData.Values["RouteName"].ToString() == "Page") 
           { 
            Response.Write(RouteData.Values["RouteName"]); 
    
           } 
    
          } 
    

    最好的方法並不難。

    相關問題