2010-10-17 19 views

Respuesta

20

Desafortunadamente, no es posible obtener el nombre de la ruta porque el nombre no es propiedad de la Ruta. Al agregar rutas a la RouteTable, el nombre se usa como un índice interno para la ruta y nunca se expone.

Hay una forma de hacerlo.

Cuando registra una ruta, configure un DataToken en la ruta con el nombre de la ruta y úselo para filtrar las rutas.

La forma más sencilla de hacer # 1 es probablemente escribir sus propios métodos de extensión para trazar rutas.

+2

mvc 4 ¿quizás? :-) –

+0

@Simon_Weaver el nombre todavía no es una propiedad en MVC 4 –

+2

¡Aún no es propiedad de Route en MVC 5! – Triynko

1

He estado enfrentando el mismo dilema, y ​​llegué a la conclusión de que, desafortunadamente, no parece haber una forma de averiguar qué ruta (por su nombre) el ASP.NET eligió para su uso.

Parece que solo puede averiguarlo por los nombres de los parámetros que pueden existir en su ruta, que aparecerán en el diccionario RouteData.Values.

Si alguien conoce una forma de llegar al nombre real de la ruta elegida por ASP.NET para una URL determinada, ¡me interesaría saber cómo hacerlo yo también!

+0

Sí, eso apesta! Tienen un mapa privado que contiene nombres y rutas, pero no hay forma de exponerlo :( – Andrey

+0

En realidad, la solución de Haacked funciona muy bien, está en mi sitio de producción ahora :) – Andrey

+0

@Andrey: sí, pero es un hack: -) y realmente preferiría una versión "adecuada" sin tener que configurar DataTokens, solo para recuperar el nombre de la ruta ... –

8

Si está trabajando con un pequeño subconjunto de rutas importantes que usted necesita para comprobar si hay (un caso especial o dos) que sólo puede hacer esto:

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

Una razón común por la que necesita el nombre de la ruta es con fines de depuración. Sigue una forma rápida y sucia de hacerlo, pero deberá agregar el nombre de cada ruta a la matriz de nombres. Debería estar bien para la depuración, especialmente si el código no se está ejecutando durante la producción.

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

Para cualquier cosa más allá de esto, debe tomarse el tiempo (mínimo) necesario para la solución de @ haacked.

+0

Gracias por la pista. Tu primera idea funcionó de maravilla para mí, porque solo necesitaba consultar en la página de un artículo si venían por la ruta del título o por la ruta de rowid. CheerZ! – eidylon

+0

Gracias amigo, también funcionó para mí. – Devsainii

7

Aquí hay una implementación de la sugerencia de @ haacked, con una sencilla tabla 'razor' para mostrar los datos de la ruta.

Nota: Es posible que no se haya dado cuenta de que todos los métodos estándar de 'MapRoute' son en realidad métodos de extensión. Por lo tanto, no podemos usar el mismo nombre. Acabo de llamarlo 'MapRoute2', porque en este momento es todo lo que puedo pensar.

Debe reemplazar todas las llamadas a MapRoute con una llamada a MapRoute2, no se olvide de todos los archivos AreaRegistration así como global.asax.cs

método de extensión:

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

Aquí hay una navaja de afeitar simple.cshtml archivo que estoy usando para mostrar la información de enrutamiento:

<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> 
+0

Así es como lo he implementado en octubre cuando Haacked lo sugirió :) De todos modos, gracias por la sugerencia – Andrey

+0

supongo que esa es la única manera ;-) es un poco doloroso escribir todas esas sobrecargas, y entonces te das cuenta necesitas duplicar para las áreas –

6

lo haría por voto respuesta de Simon_Weaver pero desafortunadamente Me he unido y no tienen los puntos de reputación para hacerlo.

Agregando a su respuesta, porque era exactamente lo que estaba buscando, aquí está la manera de hacerlo:

Tengo una enumeración pública "PageRouteTable":

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

Yo uso esta enumeración en la construcción de las rutas:

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

entonces crearon un método de extensión Página:

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

Ahora en mis páginas simplemente puede usar un interruptor de actuar en consecuencia:

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

también tengo el beneficio de las variables definidas de forma explícita y no tiene que preocuparse acerca de la codificación contra las cuerdas. Esto me ahorra un montón de dolores de cabeza en el mantenimiento.

- happy coding.

3

RouteCollection mantiene un diccionario privado de rutas con nombre.

nombres de ruta pueden ser inducidas a cabo de la misma por

  1. utilizando la reflexión para recuperar el valor del campo privado y
  2. consultar el diccionario para el elemento cuyo valor es la ruta.

El método de extensión a continuación sigue este proceso:

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

Un enfoque simple que he implementado es suministrar una clave llamada así por el parámetro '' por defecto del método .MapPageRoute. Use una constante para el valor predeterminado, y puede sacarlo de la colección Page.RouteData.Values ​​de la misma manera que lo haría normalmente.

ejemplo (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") da me

9

Fwiw 'alta', ya que se basan MVC-las extensiones y el ejemplo que se muestran por @Simon_Weaver y el poste se etiqueta con WebForms, yo pensé en compartir mis métodos de extensión basada en 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; 
    } 

Así que ahora en Global.asax.cs cuando se está registrando sus rutas, en lugar de hacerlo como routes.MapPageRoute (...) - en su lugar use el método de extensión y haga routes.MapPageRouteWithName (...)

Luego, cuando desee verificar en qué ruta se encuentra, simplemente haga Page.RouteData.GetRouteName()

Eso es todo.Sin reflexión, y las únicas referencias codificadas de "nombre de ruta" están en los dos métodos de extensión (que podrían reemplazarse con una constante si realmente lo desea).

+2

+1, gracias por salvarme el MVC -> ejercicio de traducción de WebForms. –

2

para C#, puede declarar sus rutas de este modo:

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

Luego, en el método en el que necesita la ruta a continuación, puede llamar al siguiente:

var x = Page.RouteData.Values["Section"].ToString(); 

Y tendrá una cadena configurado en su archivo.asax global para usarlo cuando lo necesite.

1

Puede agregar cada parámetros de la ruta y su innecesario Esta parámetros sean en su URL: Se puede poner el nombre de la ruta como un parámetro como esto inGlobal.asax:

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

y acceder a ella en su página :

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

       } 

      } 

La mejor manera no es la manera difícil.

Cuestiones relacionadas