Asp.net 如何从RouteData获取路线名称?

Asp.net 如何从RouteData获取路线名称?,asp.net,routing,webforms,url-routing,Asp.net,Routing,Webforms,Url Routing,我在我的Global.asax中定义了多条路线 当我在一个页面上时,我需要找出当前路由的路由名称,因为路由名称驱动我的站点菜单 如何做到这一点?我一直面临着同样的困境,我得出的结论是,不幸的是,似乎没有办法找出ASP.NET选择了哪条路线(按其名称) 似乎您只能通过路由中可能存在的参数的名称来确定,这些参数将显示在RouteData.Values字典中 如果有人知道如何获得ASP.NET为给定URL选择的路线的实际名称,我也很想知道自己如何做到这一点 不幸的是,无法获取路由的路由名称,因为该名称

我在我的Global.asax中定义了多条路线

当我在一个页面上时,我需要找出当前路由的路由名称,因为路由名称驱动我的站点菜单


如何做到这一点?

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

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


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

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

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

注册路由时,使用路由名称在路由上设置DataToken,并使用该名称筛选路由


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

如果您使用的是需要检查的重要路由的一小部分(一两个特殊情况),您可以执行以下操作:

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

这里是@haacked建议的一个实现——还有一个简单的“razor”表来显示路线数据

注意:您可能没有意识到所有标准的“MapRoute”方法实际上都是扩展方法。因此,我们不能使用相同的名称。我刚刚把它叫做“地图路线2”,因为现在我所能想到的就是这些

您必须将对MapRoute的所有调用替换为对MapRoute2的调用,不要忘记所有区域注册文件以及global.asax.cs

扩展方法:

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;
}
下面是一个简单的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>

路由密钥
价值
路线名称
@ViewContext.RouteData.DataTokens[“路由名称”]
@foreach(ViewContext.RouteData.Values中的变量路由)
{
-@route.Key
@(route.Value???)
}
@foreach(ViewContext.RouteData.DataTokens.Where中的var route(x=>x.Key!=“路由名称”))
{
@route.Key
@(route.Value???)
}

我会投票支持西蒙·韦弗的答案,但不幸的是,我刚刚加入,没有这样做的声望点

再加上他的回答,因为这正是我想要的,我的做法如下:

我有一个公共枚举“PageRouteTable”:

我在构建路由时使用此枚举:

/* -- 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;
        .
        .
        .
    }
}
我还有显式定义变量的好处,不必担心根据字符串编码。这使我在维护时省去了很多麻烦

--快乐编码。

维护命名路由的私有字典

路由名称可以通过

  • 使用反射检索私有字段和
  • 在字典中查询值为路由的项
  • 以下扩展方法遵循此过程:

    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;
    }
    
    公共静态字符串名称(此RouteBase原始)
    {
    var routes=System.Web.Routing.RouteTable.routes;
    if(路由包含(原件))
    {
    var namedMapField=routes.GetType().GetField(“_namedMap”,BindingFlags.NonPublic | BindingFlags.Instance);
    var namedMap=namedMapField.GetValue(路由)作为字典;
    变量查询=
    来自namedMap中的pair
    其中pair.Value==original
    选择pair.Key;
    返回query.Single();
    }
    返回字符串。空;
    }
    
    我实现的一个简单方法是为.MapPageRoute方法的'defaults'参数提供一个命名键。使用一个常量作为默认值,您可以按照正常方式将其从Page.RouteData.Values集合中拉出

    示例(vb.net)


    Page.RouteData.Values(“section”)
    为我提供了“stats”

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

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

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

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

    您可以添加每个路由参数,但不必在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"]);
    
                   }  
    
               }
    

    最好的方法不是艰难的方法。

    是的,那太糟糕了!他们有一张私人地图,上面有名字和路线,但没有办法公开:(事实上,哈克德的解决方案非常有效,现在在我的生产现场:)@Andrey:ye
     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"]);
    
                   }  
    
               }