很遗憾,因为名称不是Route的属性,所以无法获取路由名称。在将路由添加到RouteTable时,名称用作路由的内部索引,并且永远不会公开。
有一种方法可以解决这个问题。
在注册路由时,在路由上设置一个DataToken,并使用它来过滤路由。
做#1的最简单方法可能是编写自己的扩展方法以映射路由。
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 的解决方案。
值得一提的是,由于@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()。
这就是全部内容。没有反射,并且对“route-name”的唯一硬编码引用在两个扩展方法中(如果您真的想这样做,可以将其替换为const)。
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>
我很想为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;
.
.
.
}
}
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 文件中设置一个字符串,然后按照需要使用它。
RouteCollection维护一个私有的命名路由字典。
可以通过以下方法获取路由的名称:
下面的扩展方法遵循这个过程:
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;
}
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"]);
}
}
最好的方法不是艰难的方法。
我一直面临着同样的困境,我得出的结论是,不幸的是,似乎没有办法找出ASP.NET选择使用哪个路由(按其名称)。
看起来你只能通过你的路由中可能存在的参数名称来弄清楚这一点 - 这些将显示在RouteData.Values
字典中。
如果有人知道如何以某种方式获取ASP.NET为给定URL选择的实际路由名称,我也很想知道如何做到这一点!
routes.MapPageRoute("league-division-stats", "{league}/{division}/stats", "~/routes/league-division-stats.aspx", False, New RouteValueDictionary(New With {.section = "stats"}))
Page.RouteData.Values("section")
给了我 'stats'