У меня есть несколько маршрутов, определенных в моем Global.asax;
Когда я нахожусь на странице, мне нужно выяснить, что такое имя маршрута текущего маршрута, потому что имя маршрута управляет моим меню сайта.
Как это можно сделать?
У меня есть несколько маршрутов, определенных в моем Global.asax;
Когда я нахожусь на странице, мне нужно выяснить, что такое имя маршрута текущего маршрута, потому что имя маршрута управляет моим меню сайта.
Как это можно сделать?
К сожалению, невозможно получить имя маршрута маршрута, потому что имя не является свойством маршрута. При добавлении маршрутов в RouteTable имя используется как внутренний индекс для маршрута и никогда не отображается.
Есть один способ сделать это.
Когда вы регистрируете маршрут, установите DataToken на маршруте с именем маршрута и используйте его для фильтрации маршрутов.
Самый простой способ сделать # 1 - это, вероятно, написать собственные методы расширения для маршрутизации маршрутов.
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, когда вы регистрируете свои маршруты, вместо того, чтобы делать как route.MapPageRoute(...) - вместо этого используйте метод расширения и делаете маршруты. MapPageRouteWithName (...)
Затем, когда вы хотите проверить, на каком маршруте вы находитесь, просто сделайте Page.RouteData.GetRouteName()
Что это. Отсутствие отражения, и единственные жестко закодированные ссылки на "имя маршрута" находятся в двух методах расширения (которые можно было бы заменить на const, если вы действительно этого хотели).
Если вы работаете с небольшим подмножеством важных маршрутов, вам нужно проверить (специальный случай или два), вы можете просто сделать это:
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 - также с помощью простой таблицы "бритвы" для отображения данных маршрута.
Примечание. Возможно, вы не поняли, что все стандартные методы "MapRoute" на самом деле являются методами расширения. Поэтому мы не можем использовать одно и то же имя. Я только что назвал его "MapRoute2", потому что сейчас это все, о чем я могу думать.
Вы должны заменить все вызовы на MapRoute вызовом MapRoute2, не забудьте все файлы 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>
Я бы проголосовал за 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 поддерживает частный словарь именованных маршрутов.
Имена маршрутов можно уговорить на
Ниже описан метод расширения:
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;
}
В С# вы можете объявить свои маршруты следующим образом:
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, чтобы затем использовать по мере необходимости.
Я столкнулся с одной и той же дилеммой, и я пришел к выводу, что, к сожалению, не существует способа узнать, какой маршрут (по его названию) выбрал ASP.NET для использования.
Похоже, вы можете понять это только по именам параметров, которые могут существовать на вашем маршруте, - они будут отображаться в словаре RouteData.Values
.
Если кто-то знает способ как-то добраться до фактического имени маршрута, выбранного ASP.NET для заданного URL-адреса, мне тоже будет интересно узнать, как это сделать!
Вы можете добавить все параметры маршрута и не обязательно, чтобы эти параметры были в вашем 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"]);
}
}
Лучший способ - не сложно.
Простым подходом, который я реализовал, является предоставление именованного ключа для параметра "defaults" метода .MapPageRoute. Используйте константу по умолчанию, и вы можете вытащить ее из коллекции Page.RouteData.Values так же, как обычно.
example (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")
дает мне "статистику"