Как я могу получить имя маршрута из RouteData? - PullRequest
33 голосов
/ 17 октября 2010

У меня есть несколько маршрутов, определенных в моем Global.asax;

Когда я нахожусь на странице, мне нужно выяснить, каково название текущего маршрута, потому что имя маршрута управляет меню моего сайта.

Как это можно сделать?

Ответы [ 10 ]

22 голосов
/ 23 октября 2010

К сожалению, невозможно получить название маршрута маршрута, потому что имя не является свойством маршрута.При добавлении маршрутов в RouteTable имя используется в качестве внутреннего индекса для маршрута, и оно никогда не отображается.

Есть один способ сделать это.

Когда вы регистрируете маршрут, установитеDataToken на маршруте с именем маршрута и используйте его для фильтрации маршрутов.

Самый простой способ сделать # 1, вероятно, написать свои собственные методы расширения для отображения маршрутов.

10 голосов
/ 27 сентября 2012

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 (...) - вместо этого используйте метод расширения и выполняйте маршруты .MapPageRouteWithName (...)

Затем, когда вы хотите проверить, по какому маршруту вы находитесь, просто выполните Page.RouteData.GetRouteName ()

Вот и все. Никаких размышлений, и только жестко запрограммированные ссылки на «имя-маршрута» содержатся в двух методах расширения (которые можно заменить на const, если вы действительно этого хотите).

10 голосов
/ 19 декабря 2010

Если вы работаете с небольшим подмножеством важных маршрутов, которые вам нужно проверить (особый случай или два), вы можете просто сделать это:

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.

7 голосов
/ 19 декабря 2010

Вот реализация предложения @ 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;
    }
}

Вот простой файл бритвы .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>
6 голосов
/ 17 июня 2011

Я бы проголосовал за ответ 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;
        .
        .
        .
    }
}

У меня также есть преимущество явно определенных переменных, и я не имеюбеспокоиться о кодировании против строк.Это спасает меня от головной боли при обслуживании.

- счастливое кодирование.

3 голосов
/ 04 января 2012

RouteCollection поддерживает частный словарь именованных маршрутов.

Имена маршрутов могут быть выведены из него с помощью

  1. , используя отражение для получения значенияприватное поле и
  2. запрос словаря для элемента, значением которого является маршрут.

Ниже описан метод расширения:

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;
}
2 голосов
/ 21 июня 2013

Для 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 будет установлена ​​строка для последующего использования по мере необходимости.

1 голос
/ 21 ноября 2013

Вы можете добавить все параметры маршрута, и в этом нет необходимости, чтобы эти параметры были в вашем URL: Вы можете указать название своего маршрута в качестве параметра, подобного этому, в global.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"]);

               }  

           }

Лучший способ - не трудный путь.

1 голос
/ 17 октября 2010

Я столкнулся с той же дилеммой, и я пришел к выводу, что, к сожалению, нет способа выяснить, какой маршрут (по названию) выбрал ASP.NET для использования.

Кажется, вы можете понять это только по именам параметров, которые могут существовать в вашем маршруте - они будут отображаться в словаре RouteData.Values.

Если кто-то знает способ как-то получитьпри фактическом названии маршрута, выбранного ASP.NET для данного URL, мне было бы интересно узнать, как сделать это и самому!

0 голосов
/ 24 февраля 2012

Простой подход, который я реализовал, состоит в том, чтобы предоставить именованный ключ для параметра 'defaults' метода .MapPageRoute. Используйте константу по умолчанию, и вы можете извлечь ее из коллекции 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") дает мне статистику

...