代码之家  ›  专栏  ›  技术社区  ›  Andrey

如何从RouteData获取路线名称?

  •  32
  • Andrey  · 技术社区  · 15 年前

    当我在一个页面上时,我需要弄清楚当前路由的路由名称是什么,因为路由名称驱动着我的站点菜单。

    怎么能做到?

    10 回复  |  直到 12 年前
        1
  •  23
  •   Haacked    15 年前

    很遗憾,无法获取路由的路由名称,因为该名称不是路由的属性。向RouteTable添加路由时,该名称将用作路由的内部索引,并且不会公开。

    注册路由时,请使用路由名称在路由上设置一个DataToken,并使用它筛选路由。

    最简单的方法是编写自己的扩展方法来映射路由。

        2
  •  11
  •   kman    13 年前

        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(…)

    就这样。没有反射,对“route name”的唯一硬编码引用在两个扩展方法中(如果您真的想的话,可以用const替换)。

        3
  •  11
  •   DeveloperDan Asaf    9 年前

    如果您使用的是需要检查的重要路由的一小部分(一两个特例),您可以这样做:

    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解决方案所需的(最少)时间。

        4
  •  7
  •   Simon_Weaver    15 年前

    下面是@haacked建议的一个实现——还有一个简单的“razor”表来显示路由数据。

    注意:您可能还没有意识到所有标准的“MapRoute”方法实际上都是扩展方法。所以我们不能用同一个名字。我刚刚把它叫做“MapRoute2”,因为现在我能想到的就是这个。

    必须用对MapRoute2的调用替换对MapRoute的所有调用,不要忘记所有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;
        }
    }
    

    下面是一个简单的razor.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>
    
        5
  •  6
  •   MikeAtCodeSmart    15 年前

    我会投票给西蒙韦弗的答案,但不幸的是,我只是加入了,没有这样做的声誉点。

    加上他的回答,因为这正是我要找的,我是这样做的:

    我有一个公共枚举“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;
            .
            .
            .
        }
    }
    

    --快乐的编码。

        6
  •  3
  •   Samu Lang    14 年前

    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;
    }
    
        7
  •  2
  •   Andrew Berry    13 年前

            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();
    

    在global.asax中设置一个字符串,然后根据需要使用。

        8
  •  1
  •   marc_s MisterSmith    15 年前

    我一直面临着同样的困境,我得出的结论是,不幸的是,似乎没有办法找出ASP.NET选择的使用路径(按其名称)。

    似乎您只能通过路由中可能存在的参数的名称来确定这些参数将显示在 RouteData.Values 字典。

    如果有人知道如何获取ASP.NET为给定URL选择的路由的实际名称,我也很想知道如何做到这一点!

        9
  •  1
  •   Farhawd    12 年前

    您可以添加每个路由参数,而这些参数不必出现在您的Url中: 您可以将路由名称作为一个参数,如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"]);
    
                   }  
    
               }
    

    最好的方法不难。

        10
  •  0
  •   ScottE    14 年前

    示例(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") 给我“统计”

    推荐文章