How do I get Route name from RouteData?

前端 未结 10 881
猫巷女王i
猫巷女王i 2021-02-05 02:03

I have several routes defined in my Global.asax;

When I\'m on a page I need to figure out what is the route name of the current route, because route name drives my site

相关标签:
10条回答
  • 2021-02-05 02:22

    FWIW, since the extensions and example shown by @Simon_Weaver are MVC-based and the post is tagged with WebForms, I thought I'd share my WebForms-based extension methods:

        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;
        }
    

    So now in Global.asax.cs when you're registering your routes, instead of doing like routes.MapPageRoute(...) - instead use the extension method and do routes.MapPageRouteWithName(...)

    Then when you want to check what route you're on, simply do Page.RouteData.GetRouteName()

    That's it. No reflection, and the only hard-coded references to "route-name" are in the two extension methods (which could be replaced with a const if you really wanted to).

    0 讨论(0)
  • 2021-02-05 02:24

    RouteCollection maintains a private dictionary of named routes.

    Route names can be coaxed out of it by

    1. using reflection to retrieve the value of the private field and
    2. querying the dictionary for the item whose value is the route.

    The extension method below follows this process:

    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;
    }
    
    0 讨论(0)
  • 2021-02-05 02:27

    I would up-vote Simon_Weaver's answer but unfortunately I just joined and do not have the reputation points to do so.

    Adding to his answer, because it was exactly what I was looking for, here's the way I do it:

    I have a public enum "PageRouteTable":

    public enum PageRouteTable
    {
        // -- User Area
        UserArea_Locations,
        UserArea_Default,
        UserArea_PasswordReset,
        UserArea_Settings,
        .
        .
        .
    }
    

    I use this enum when building the routes:

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

    I then created a Page extension method:

    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;
    }
    

    Now in my pages I can simply use a switch to act upon it:

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

    I also have the benefit of explicitly defined variables and do not have to worry about coding against strings. This saves me a ton of headaches in maintenance.

    -- happy coding.

    0 讨论(0)
  • 2021-02-05 02:29

    If you're working with a small subset of important routes you need to check for (a special case or two) you can just do this :

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

    A common reason for needing the route name is for debugging purposes. A quick and dirty way to do this follows - but you'll need to add each route name to the array of names. Should be fine for debugging - especially if the code isn't running during production.

    // 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
    }
    

    For anything beyond this you should take the (minimal) time needed for @haacked's solution.

    0 讨论(0)
  • 2021-02-05 02:30

    You can add every route parameters and its not necessary this parameters be in your Url: You can put your route name as a parameter like this inGlobal.asax:

     routes.MapPageRoute("Page",
                    "Page-{ID}",
                   "~/Item_show.aspx", false, new RouteValueDictionary{ { "RouteName" , "Page" }});
    

    And Access it in your page:

    if (RouteData.Values["RouteName"] != null)
               {
                   if (RouteData.Values["RouteName"].ToString() == "Page")
                   {
                       Response.Write(RouteData.Values["RouteName"]);
    
                   }  
    
               }
    

    Best way is not hard way.

    0 讨论(0)
  • 2021-02-05 02:31

    Unfortunately, it's not possible to get the route name of the route because the name is not a property of the Route. When adding routes to the RouteTable, the name is used as an internal index for the route and it's never exposed.

    There's one way to do this.

    When you register a route, set a DataToken on the route with the route name and use that to filter routes.

    The easiest way to do #1 is to probably write your own extension methods for mapping routes.

    0 讨论(0)
提交回复
热议问题