2010-10-17 99 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"]); 
    
           } 
    
          } 
    

    最好的方法并不难。