ASP.NET MVC Preview 5 を使用すると (ベータ版でも試しましたが)、ルート内のクエリ文字列のデフォルトがクエリ文字列で渡される値を上書きするようです。再現するには、次のようなコントローラーを記述します。
public class TestController : Controller
{
public ActionResult Foo(int x)
{
Trace.WriteLine(x);
Trace.WriteLine(this.HttpContext.Request.QueryString["x"]);
return new EmptyResult();
}
}
ルートは次のようにマップされます。
routes.MapRoute(
"test",
"Test/Foo",
new { controller = "Test", action = "Foo", x = 1 });
そして、この相対 URI で呼び出します。
/Test/Foo?x=5
表示されるトレース出力は次のとおりです。
1
5
つまり、ルートに設定されたデフォルト値は、クエリ文字列に実際に指定されたかどうかに関係なく、常にメソッドに渡されます。クエリ文字列のデフォルトが削除された場合、つまりルートが次のようにマップされる場合は注意してください。
routes.MapRoute(
"test",
"Test/Foo",
new { controller = "Test", action = "Foo" });
その後、コントローラーは期待どおりに動作し、値がパラメーター値として渡され、トレース出力が生成されます。
5
5
これはバグのように見えますが、デフォルト付きのクエリ文字列はそれほど難解な機能でもエッジケースの機能でもないので、このようなバグが ASP.NET MVC フレームワークのベータ リリースにまだ存在するというのは非常に驚きです。したがって、これはほぼ間違いなく私のせいです。私が何を間違っているのか、何かアイデアはありますか?
ベストアンサー1
QueryString を使用する ASP.NET MVC を理解するための最善の方法は、QueryString をルートが認識しない値として考えることです。おわかりのように、QueryString は RouteData の一部ではないため、クエリ文字列として渡すものをルート値とは別にしておく必要があります。
これらを回避する方法としては、QueryString から渡された値が null の場合に、アクション内でデフォルト値を自分で作成することです。
あなたの例では、ルートは x を認識しているため、URL は実際には次のようになります。
/Test/Foo or /Test/Foo/5
ルートは次のようになります。
routes.MapRoute("test", "Test/Foo/{x}", new {controller = "Test", action = "Foo", x = 1});
求めていた動作を実現します。
ページ番号のような QueryString 値を渡す場合は、次のようにします。
/Test/Foo/5?page=1
そして、あなたの行動は次のように変わるはずです:
public ActionResult Foo(int x, int? page)
{
Trace.WriteLine(x);
Trace.WriteLine(page.HasValue ? page.Value : 1);
return new EmptyResult();
}
さて、テストです:
Url: /Test/Foo Trace: 1 1 Url: /Test/Foo/5 Trace: 5 1 Url: /Test/Foo/5?page=2 Trace: 5 2 Url: /Test/Foo?page=2 Trace: 1 2
これがいくつかの点を明確にするのに役立つことを願っています。