2011-01-20 9 views
13

文字列が特定の名前付きルートに一致するかどうかを確認するにはどうすればよいですか?任意のURLが定義済みのルートに一致するかどうかを判断する方法

私はこのようなルートを持っている:「URL」の文字列がそのルートと一致した場合に

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" 

どのように私はプログラム的に伝えることができますか?このような何か:

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

これは、他のウリの拡張メソッドの創出につながっ?コントローラー、フィルター、または...? – frennky

+0

コントローラ内。私はルートが3つの特定のルートの1つに合っているかどうかを判断する必要があり、その3つのそれぞれに対して別個のアクションをとる必要があります。 – Scott

+0

なぜあなたはそれをやってくれるのですか?代わりに3つの別々の行動を取ってみませんか? – frennky

答えて

13

私が指定したurlとアプリケーションのパスとのHttpContext新しいを作成し、新しいHttpContextオブジェクトに基づいてRouteDataのインスタンスを取得することを使用するカスタムRouteInfoクラスを追加することでこれを解決しました。次に、コントローラとアクションの値を評価して、どのルートがマッチしたかを調べることができます。私はこれをUriクラスの拡張メソッドに配線しました。これはちょっとハッキリしているように感じました。私はこれを行うためのよりクリーンな方法があることを望んでいたので、他の誰かがより良い解決策を持っている場合に備えて質問を開いたままにします。

ROUTEINFO CLASS:

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拡張メソッド:

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

USAGE:

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

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

OR

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

を追加しましたBONUS: RouteInfoクラスは私にRouteDataのインスタンスをバック与えるので、私は同様の経路パラメータにアクセスすることができます。

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

今では同じように使用することができます:あなたは、このメソッドを使用する予定行う

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

mvccontribにはルートの単体テストを目的としたテストヘルパーライブラリがあります。 RouteDataオブジェクトを作成する文字列の拡張メソッドがあります。なぜなら、これはコード・プレックスのオープン・ソース・プロジェクトなので、ソース・コードでいくつかのアイデアを確認することをお勧めします。 – frennky

+0

これは基本的に私が行ったことです(Uriオブジェクトを除いて)が、MvcContribテストヘルパーのようにRhino Mocksを使わなくてもHttpContextのインスタンスを作成しました。 – Scott

+2

私は、クエリ文字列パラメータが二重にエンコードされていることにいくつか問題がありました。これは、_pathInfoがクエリ文字列に設定されているために発生しました。この結果、urlの最後の部分(私の場合はaction値)がクエリー文字列を間違って含むため、二重にエンコードされます。私はこれを修正するために上記のコードを修正しました。 – stusherwin

関連する問題