2011-01-20 4 views
13

Come posso sapere se una stringa corrisponde a una determinata rotta denominata?Come determinare se un URL arbitrario corrisponde a un percorso definito

Ho un percorso come questo:

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" 

Come posso programmazione dire se la stringa 'url' corrisponde a quella strada? Qualcosa di simile a questo:

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

in cui avete intenzione di utilizzare questo metodo? in un controller, filtro o ...? – frennky

+0

In un controller. Devo determinare se la rotta corrisponde a una delle tre rotte particolari e per ognuna di queste tre ho bisogno di un'azione separata. – Scott

+0

Non capisco perché lo faresti? perché non hai invece tre azioni separate? – frennky

risposta

13

Ho risolto questo con l'aggiunta di una classe RouteInfo personalizzato che crea un nuovo HttpContext con il percorso URL e applicazione in dotazione e lo utilizza per ottenere un'istanza di RouteData sulla base del nuovo oggetto HttpContext. Posso quindi valutare i valori del controller e dell'azione per vedere quale rotta è stata abbinata. Ho questo collegato a un metodo di estensione sulla classe Uri. Sembra un po 'hacker e speravo che ci fosse un modo più pulito per farlo, quindi lascerò aperta la domanda nel caso in cui qualcun altro abbia una soluzione migliore.

ROUTEINFO CLASSE:

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 Metodo di estensione:

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

AGGIUNTO BONUS: Poiché la classe RouteInfo mi restituisce un'istanza di RouteData, posso accedere parametri del percorso pure. Ciò ha portato alla creazione di un altro metodo di estensione 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; 
     } 

che ora può essere utilizzato in questo modo:

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

mvccontrib ha una libreria di test helper che è pensata per il test unitario delle rotte. esiste un metodo di estensione per la stringa che crea l'oggetto RouteData. dal momento che si tratta di un progetto open source su codeplex, suggerisco di controllare il codice sorgente per alcune idee. – frennky

+0

Questo è essenzialmente ciò che ho fatto (eccetto sull'oggetto Uri), ma ho creato un'istanza di HttpContext senza dover usare Rhino Mocks come fa l'helper di test MvcContrib. – Scott

+2

Stavo riscontrando alcuni problemi con i parametri della stringa di query con doppia codifica. Ho capito che questo era dovuto al fatto che _pathInfo era impostato sulla stringa di query.Ciò risulta nell'ultima parte dell'URL (nel mio caso il valore dell'azione) includendo erroneamente la stringa di query e quindi essendo doppia codificata. Ho corretto il codice sopra per risolvere questo problema. – stusherwin