次の形式で別のシステムからURLを取得するために、MVCでカスタムルートを設定しようとしています。
../ABC/ABC01?Key=123&Group=456
2番目のABCの後の01は、これが変更されるステップ番号であり、キーとグループのパラメーターが変更されます。パラメータとしてステップ番号キーとグループを使用して、これをコントローラーの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.`
ルートにクエリ文字列を含めることはできません。次のようなルートで試してください:
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は、クエリ文字列パラメーターをコントローラーのメソッドのパラメーターに自動的にマップします。
ルートを定義するとき、ルートの先頭で/
を使用することはできません。
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をキャッチしてアクションに送信します。
新しいASP.NET MVCプロジェクトでクエリ文字列に基づくルーティングを使用する理由はありません。従来のASP.NETプロジェクトから変換された古いプロジェクトで、URLを保持したい場合に役立ちます。
1つのソリューションは、属性ルーティングです。
別のソリューションは、RouteBaseから派生することにより、カスタムルーティングを作成することです。
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;
}
}
カスタムルーティングクラスを登録します
public static void RegisterRoutes(RouteCollection routes)
{
...
routes.Add(new MyOldClassicAspRouting ());
}
クエリ文字列の引数は通常、そのコントローラーとその特定のアプリケーションロジックに固有です。
したがって、これが一般的なルートルールで記述されていない方が良いでしょう。
次の方法で、アクション引数にクエリ文字列の検出を埋め込むことができます。
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メソッドはクエリ文字列分割ロジックを処理します。
そして、この方法でルーティングを続けます。ルーティングはid引数でクエリ文字列を取得することに注意してください。
routes.MapRoute(
"OpenCase",
"ABC/OpenCase/{id}",
new {controller = "ABC", action = "OpenCase"}
);
このメソッドを使用して、コントローラーアクションで複数のフィールドのキー値を取得しました。