2011-08-04 8 views
29

私は、次の形式で別のシステムからURLを取るために、セットアップにMVCでのカスタムルートを試みている:クエリー文字列を含むURLをASP.NET MVCにルーティングするにはどうすればよいですか?

../ABC/ABC01?Key=123&Group=456

01秒ABCはこれが変更されますステップ番号とキーです後グループパラメータが変更されます。私はこれを、ステップ番号キーとグループをパラメタとしてコントローラ内の1つのアクションにルーティングする必要があります。しかし私は、次のコードを実行しようとしましたしました、それは例外をスロー:

コード:

routes.MapRoute(
    "OpenCase", 
    "ABC/ABC{stepNo}?Key={key}&Group={group}", 
    new {controller = "ABC1", action = "OpenCase"} 
); 

例外:

`The route URL cannot start with a '/' or '~' character and it cannot contain a '?' character.` 

答えて

35

あなたがルートでクエリ文字列を含めることはできません。このようなルートで試してみてください:

routes.MapRoute("OpenCase", "ABC/ABC{stepNo}", 
    new { controller = "ABC1", action = "OpenCase" }); 

次に、あなたのコントローラ上で、次のようにメソッドを追加します。

public class ABC1 : Controller 
{ 
    public ActionResult OpenCase(string stepno, string key, string group) 
    { 
     // do stuff here 
     return View(); 
    }   
} 

ASP.NET MVCは自動的にメソッド内でパラメータにクエリ文字列パラメータをマッピングしますコントローラ。ルートを定義する際

4

、あなたはルートの最初に/を使用することはできません。

routes.MapRoute("OpenCase", 
    "/ABC/{controller}/{key}/{group}", <-- Bad; see/at beginning 
    new { controller = "", action = "OpenCase" }, 
    new { key = @"\d+", group = @"\d+" } 
    ); 

routes.MapRoute("OpenCase", 
    "ABC/{controller}/{key}/{group}", <-- Good; No/at beginning 
    new { controller = "", action = "OpenCase" }, 
    new { key = @"\d+", group = @"\d+" } 
    ); 

はこれを試してみてください:

routes.MapRoute("OpenCase", 
    "ABC/{controller}/{key}/{group}", 
    new { controller = "", action = "OpenCase" }, 
    new { key = @"\d+", group = @"\d+" } 
    ); 

次のように次に、あなたのアクションが見えるはずです。

public ActionResult OpenCase(int key, int group) 
{ 
    //do stuff here 
} 

あなたはstepNoと " ABC "を入力してコントローラーを取得します(ABC1)。だから私はURLのその部分を{controller}に置き換えたのです。

「キー」と「グループ」を定義するルートもあるため、上記のルートでも最初のURLがキャッチされ、アクションに送信されます。

1

新しいASP.NET MVCプロジェクトでクエリ文字列に基づくルーティングを使用する理由はありません。これは、古典的なASP.NETプロジェクトから変換され、URLを保持したい古いプロジェクトに役立ちます。

1つの解決策は、属性ルーティングです。クエリ文字列引数は、一般的にそのコントローラのと、その特定のある

public static void RegisterRoutes(RouteCollection routes) 
{ 
    ... 

    routes.Add(new MyOldClassicAspRouting()); 
} 
0

public class MyOldClassicAspRouting : RouteBase 
{ 

    public override RouteData GetRouteData(HttpContextBase httpContext) 
    { 
    if (httpContext.Request.Headers == null) //for unittest 
     return null; 

    var queryString = httpContext.Request.QueryString; 

    //add your logic here based on querystring 
    RouteData routeData = new RouteData(this, new MvcRouteHandler()); 
    routeData.Values.Add("controller", "..."); 
    routeData.Values.Add("action", "..."); 
    } 

    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) 
    { 
    //Implement your formating Url formating here 
    return null; 
    } 
} 

そして、あなたのカスタムルーティングクラスを登録します。

別の解決策は、RouteBaseから派生してカスタムルーティングを足すにすることができ特定のアプリケーションロジック。

これは一般的なルートルールに記載されていない方が良いでしょう。

アクション引数にクエリ文字列の検出を次のように埋め込むことができます。

StepNoを処理するコントローラが1台ある方が良いと思います。

public class ABC : Controller 
{ 
    public ActionResult OpenCase(OpenCaseArguments arg) 
    { 
     // do stuff here 
     // use arg.StepNo, arg.Key and arg.Group as You need 
     return View(); 
    }   
} 

public class OpenCaseArguments 
{ 
    private string _id; 
    public string id 
    { 
     get 
     { 
      return _id; 
     } 

     set 
     { 
      _id = value; // keep original value; 
      ParseQueryString(value); 
     } 
    } 

    public string StepNo { get; set; } 
    public string Key { get; set; } 
    public string Group { get; set; } 

    private void ParseQueryString(string qs) 
    { 
     var n = qs.IndexOf('?'); 
     if (n < 0) return; 
     StepNo = qs.Substring(0, n); // extract the first part eg. {stepNo} 
     NameValueCollection parms = HttpUtility.ParseQueryString(qs.Substring(n + 1)); 
     if (parms.Get("Key") != null) Key = parms.Get("Key"); 
     if (parms.Get("Group") != null) Group = parms.Get("Group"); 
    } 

} 

ModelBinderは、OpenCaseArgumentsのidフィールドに{id}値を割り当てます。 setメソッドはquerystring splitロジックを処理します。

このようにルーティングしてください。ルーティングはID引数でクエリ文字列を取得します。

routes.MapRoute(
    "OpenCase", 
    "ABC/OpenCase/{id}", 
    new {controller = "ABC", action = "OpenCase"} 
); 

このメソッドを使用して、コントローラのアクションで複数のフィールドのキー値を取得しました。

+0

MVCが自動的にクエリ文字列を 'QueryStringValueProvider'で解析することに注意してください。アクションメソッドでこれらの値を取得するために必要なのは、クエリメソッドの文字列キーと同じ名前のパラメーターをアクションメソッドまたはモデルに追加することだけです。このために独自のクエリ文字列パーサーを構築する必要はありません。 – NightOwl888

関連する問題