如何从RouteData获取路由名称?

And*_*rey 33 asp.net routing webforms url-routing

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

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

如何才能做到这一点?

Haa*_*ked 23

不幸的是,由于名称不是Route的属性,因此无法获取路径的路径名称.将路由添加到RouteTable时,该名称将用作路径的内部索引,并且永远不会公开.

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

当您注册一个路由,路由名称的路线上设置的DataToken并用它来过滤路由.

做#1,最简单的方式是可能会写自己的扩展方法映射路线.

  • 也许mvc 4?:-) (2认同)
  • 仍然不是MVC 5中Route的属性! (2认同)

Sim*_*ver 11

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

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

需要路由名称的常见原因是出于调试目的.下面是一种快速而肮脏的方法 - 但您需要将每个路由名称添加到名称数组中.应该可以正常进行调试 - 特别是如果代码在生产期间没有运行.

// 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
}
Run Code Online (Sandbox Code Playgroud)

对于超出此范围的任何事情,您应该花费@haacked解决方案所需的(最少)时间.


kma*_*man 11

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;
    }
Run Code Online (Sandbox Code Playgroud)

所以现在在Global.asax.cs中注册路由时,而不是像routes.MapPageRoute(...)那样 - 而是使用扩展方法并执行routes.MapPageRouteWithName(...)

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

而已.没有反射,并且对"route-name"的唯一硬编码引用是在两个扩展方法中(如果你真的想要,可以用const替换).

  • +1,谢谢你救了我MVC - > WebForms翻译练习. (3认同)

Sim*_*ver 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是一个简单的剃​​刀.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>
Run Code Online (Sandbox Code Playgroud)


Mik*_*art 6

我会对Simon_Weaver的答案进行投票,但遗憾的是我刚加入并且没有声誉点.

添加他的答案,因为它正是我所寻找的,这就是我的方式:

我有一个公共枚举"PageRouteTable":

public enum PageRouteTable
{
    // -- User Area
    UserArea_Locations,
    UserArea_Default,
    UserArea_PasswordReset,
    UserArea_Settings,
    .
    .
    .
}
Run Code Online (Sandbox Code Playgroud)

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

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

然后我创建了一个Page扩展方法:

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;
}
Run Code Online (Sandbox Code Playgroud)

现在,在我的页面中,我可以简单地使用开关来对其进行操作:

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

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

- 快乐的编码.