如何从RouteData获取路由名称?

时间:2010-10-17 18:37:25

标签: asp.net routing webforms url-routing

我在Global.asax中定义了几条路线;

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

如何做到这一点?

10 个答案:

答案 0 :(得分:21)

不幸的是,无法获取路线的路线名称,因为该名称不是路线的属性。将路由添加到RouteTable时,该名称将用作路径的内部索引,并且永远不会暴露。

有一种方法可以做到这一点。

注册路线时,请在路线上设置包含路线名称的DataToken,并使用该路径过滤路线。

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

答案 1 :(得分:10)

如果您正在处理一小部分重要路线,您需要检查(特殊情况或两个),您可以这样做:

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

答案 2 :(得分: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中注册你的路线,而不是做类似的路线.MapPageRoute(...) - 而是使用扩展方法并做routes.MapPageRouteWithName(...)< / p>

然后,当您想要检查您所处的路线时,只需执行Page.RouteData.GetRouteName()

那就是它。没有反思,唯一的硬编码引用&#34; route-name&#34;在两个扩展方法中(如果你真的想用它可以用const替换)。

答案 3 :(得分:7)

这是@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;
    }
}

这是一个简单的剃​​刀.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>

答案 4 :(得分: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;
        .
        .
        .
    }
}

我也有明确定义的变量的好处,不必担心对字符串进行编码。这为我节省了大量的维护麻烦。

- 快乐的编码。

答案 5 :(得分:3)

RouteCollection维护一个名为routes的私人字典。

可以通过

哄骗路线名称
  1. 使用反射来检索私有字段的值和
  2. 查询字典,查找值为路径的项目。
  3. 以下扩展方法遵循以下流程:

    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;
    }
    

答案 6 :(得分:2)

对于C#,您可以声明您的路线:

        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中设置一个字符串,然后根据需要使用。

答案 7 :(得分:1)

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

您似乎只能通过路线中可能存在的参数名称来计算出来 - 这些参数会显示在RouteData.Values词典中。

如果有人知道某种方式可以获得ASP.NET为给定URL选择的路由的实际名称,我也有兴趣知道如何自己这样做!

答案 8 :(得分:1)

您可以添加每个路线参数,而不必将此参数添加到您的网址中: 您可以将路径名称作为参数放在thisGlobal.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"]);

               }  

           }

最好的方法并不难。

答案 9 :(得分:0)

我实现的一个简单方法是为.MapPageRoute方法的'defaults'参数提供一个命名键。使用常量作为默认值,您可以像往常一样将它从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")给了'统计'