2011-01-20 14 views
13

¿Cómo puedo saber si una cadena coincide con una determinada ruta con nombre?Cómo determinar si una URL arbitraria coincide con una ruta definida

que tienen una ruta como esta:

routes.MapRoute(
    "FindYourNewRental", 
    "find-your-new-rental/{market}/{community}.html", 
    new { controller = "FindYourNewRental", action = "Community" } 
    ); 

string url = "http://www.website.com/find-your-new-rental/northerncalifornia/sacramento.html" 

¿Cómo puedo saber si mediante programación la cadena 'url' coincide con esa ruta? Algo como esto:

// matches url with the named route "FindYourNewRental" 
if (IsRouteMatch(url, "FindYourNewRental")) 
{ 
    // do something 
} 

public bool IsRouteMatch(string url, string routeName) 
{ 
    // How do I code this function 
} 
+0

¿dónde tiene la intención de utilizar este método? en un controlador, filtro o ...? – frennky

+0

En un controlador. Necesito determinar si la ruta coincide con una de las tres rutas particulares y para cada una de esas tres necesito tomar una acción por separado. – Scott

+0

No entiendo muy bien por qué harías eso? ¿Por qué no tienes tres acciones separadas en su lugar? – frennky

Respuesta

13

He resuelto esto añadiendo una clase RouteInfo a medida que crea un nuevo HttpContext con la ruta URL y aplicación suministrada y la usa para obtener una instancia de RouteData basado en el nuevo objeto HttpContext. Luego puedo evaluar los valores de Controlador y Acción para ver qué ruta coincidió. Tengo esto conectado a un método de extensión en la clase Uri. Me siento un poco hambriento y esperaba que hubiera una manera más limpia de hacerlo, así que dejaré la pregunta abierta en caso de que alguien más tenga una mejor solución.

ROUTEINFO CLASE:

public class RouteInfo 
    { 
     public RouteInfo(RouteData data) 
     { 
      RouteData = data; 
     } 

     public RouteInfo(Uri uri, string applicationPath) 
     { 
      RouteData = RouteTable.Routes.GetRouteData(new InternalHttpContext(uri, applicationPath)); 
     } 

     public RouteData RouteData { get; private set; } 

     private class InternalHttpContext : HttpContextBase 
     { 
      private readonly HttpRequestBase _request; 

      public InternalHttpContext(Uri uri, string applicationPath) : base() 
      { 
       _request = new InternalRequestContext(uri, applicationPath); 
      } 

      public override HttpRequestBase Request { get { return _request; } } 
     } 

     private class InternalRequestContext : HttpRequestBase 
     { 
      private readonly string _appRelativePath; 
      private readonly string _pathInfo; 

      public InternalRequestContext(Uri uri, string applicationPath) : base() 
      { 
       _pathInfo = ""; //uri.Query; (this was causing problems, see comments - Stuart) 

       if (String.IsNullOrEmpty(applicationPath) || !uri.AbsolutePath.StartsWith(applicationPath, StringComparison.OrdinalIgnoreCase)) 
        _appRelativePath = uri.AbsolutePath; 
       else 
        _appRelativePath = uri.AbsolutePath.Substring(applicationPath.Length); 
      } 

      public override string AppRelativeCurrentExecutionFilePath { get { return String.Concat("~", _appRelativePath); } } 
      public override string PathInfo { get { return _pathInfo; } } 
     } 
    } 

URI Método de extensión:

/// <summary> 
    /// Extension methods for the Uri class 
    /// </summary> 
    public static class UriExtensions 
    { 
     /// <summary> 
     /// Indicates whether the supplied url matches the specified controller and action values based on the MVC routing table defined in global.asax. 
     /// </summary> 
     /// <param name="uri">A Uri object containing the url to evaluate</param> 
     /// <param name="controllerName">The name of the controller class to match</param> 
     /// <param name="actionName">The name of the action method to match</param> 
     /// <returns>True if the supplied url is mapped to the supplied controller class and action method, false otherwise.</returns> 
     public static bool IsRouteMatch(this Uri uri, string controllerName, string actionName) 
     { 
      RouteInfo routeInfo = new RouteInfo(uri, HttpContext.Current.Request.ApplicationPath); 
      return (routeInfo.RouteData.Values["controller"].ToString() == controllerName && routeInfo.RouteData.Values["action"].ToString() == actionName); 
     } 
    } 

USO:

Uri url = new Uri("http://www.website.com/find-your-new-rental/northerncalifornia/sacramento.html"); 

if (url.IsRouteMatch("FindYourNewRental", "Community")) 
{ 
    // do something 
} 

O

if (Request.Url.IsRouteMatch("FindYourNewRental", "Community")) 
    { 
     // do something 
    } 

Un valor añadido: Porque la clase RouteInfo me devuelve una instancia de RouteData, puedo acceder a los parámetros de la ruta también. Esto condujo a la creación de otro método de extensión Uri:

public static string GetRouteParameterValue(this Uri uri, string paramaterName) 
     { 
      RouteInfo routeInfo = new RouteInfo(uri, HttpContext.Current.Request.ApplicationPath); 
      return routeInfo.RouteData.Values[paramaterName] != null ? routeInfo.RouteData.Values[paramaterName].ToString() : null; 
     } 

que ahora puede ser utilizado de esta manera:

string someValue = url.GetRouteParameterValue("ParameterName"); 
+0

mvccontrib tiene una biblioteca auxiliar de prueba que está destinada a probar unidades de rutas. hay un método de extensión para cadena que crea el objeto RouteData. dado que es un proyecto de código abierto en Codeplex, le sugiero que consulte el código fuente para obtener algunas ideas. – frennky

+0

Eso es esencialmente lo que he hecho (excepto en el objeto Uri), pero he creado una instancia de HttpContext sin tener que usar Rhino Mocks como hace el asistente de prueba MvcContrib. – Scott

+2

Estaba teniendo algunos problemas con los parámetros de la cadena de consulta con doble codificación. Me di cuenta de que esto se debía a que _pathInfo se había establecido en la cadena de consulta.Esto da como resultado que la última parte de la url (en mi caso, el valor de acción) incluya erróneamente la cadena de consulta y, por lo tanto, tenga una codificación doble. He corregido el código anterior para solucionarlo. – stusherwin

Cuestiones relacionadas