ASP.NET MVC 4 ことはじめ(3)ルーティング
ルーティングについて
アクセスされたURLに対して、どのコントローラを起動するか割り当てることを「ルーティング」と呼びます。ルーティング定義は、Global.asax の Application_Start() で設定します。
ASP.NET MVC 3 までは、ルート定義をカスタマイズする際に直接 Global.asax 内に書いていましたが、ASP.NET MVC 4 からは App_Start/RouteConfig.cs に書くことになっています。自動生成されたソースコードがすでにそうなっています。
Global.asax を開いてみてください。Application_Start() 内で RouteConfig.RegisterRoutes() を呼び出しています。
他にも、BundleConfig, FilterConfig, WebApiConfig など、Application_Start() 内で呼び出すコンフィグは App_Start フォルダにまとめられています。
ルーティング定義
では、自動生成されたソースコードのルーティング定義を見てみましょう。
App_Start/RouteConfig.cs
namespace HelloWorld1 { public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); // オマジナイ routes.MapRoute( name: "Default", // 定義名 url: "{controller}/{action}/{id}", // ルーティング情報 defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } // デフォルト ); } } }
IgnoreRoute() はリソースデータに直接アクセスされない為のオマジナイです。
MapRoute() でルート定義をマッピングしていますね。
name: "Default"
これは単にルート定義の名前です。
url: "{controller}/{action}/{id}"
これはURLの構造とマッピングを表しています。
例えば、 http://localhost:53280/Abc/Def/12 というリクエストURLだった場合、AbcController クラスの Def() メソッドが呼び出され、引数 id に 12 が渡される、という具合です。
このとき、URLの大文字小文字は関係ありません。
http://localhost:53280/aBc/deF/12 としても呼び出されるコントローラメソッドはやはり AbcController.Def() です。
最後に、
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
ですが、これはデフォルトの定義を表していて、リクエストURLで明示されなかった場合にどの値とみなすか、といった解釈でよいと思います。トップURLへのアクセスで HomeController.Index() が呼び出されるのはこのデフォルト定義があるためです。パラメータ「id」はOptional、つまり省略可能であることを表しています。
したがって、このルーティング設定では以下のような認識となります。
リクエストURL | controller | action | id |
---|---|---|---|
http://localhost:53280/Abc/Def/12 | Abc | Def | 12 |
http://localhost:53280/Abc/Def | Abc | Def | null |
http://localhost:53280/Abc | Abc | Index | null |
http://localhost:53280/ | Home | Index | null |
実際に AbcController を作成し、Defメソッドを作って試してみると、動きがよくわかると思います。
Controllers/AbcController.cs
namespace HelloWorld1.Controllers { public class AbcController : Controller { // // GET: /Abc/ public ActionResult Index() { return View(); } // // GET: /Abc/Def/id public ActionResult Def(string id) { ViewData["msg"] = "Defメソッドです。id は[" + id + "]です。"; return View(); } } }
ビューは Index と Def の2つを作っておきましょう。(先に Views/Abc フォルダを作る必要があります)
Views/Abc/Index.cshtml
@{ ViewBag.Title = "Index"; } <h2>Abc Index</h2> <p> @ViewData["msg"] </p>
Views/Abc/Def.cshtml
@{ ViewBag.Title = "Def"; } <h2>Abc Def</h2> <p> @ViewData["msg"] </p>
では実行してみましょう。
ブラウザのURLを以下のように直接打ち変えてみて、どのような動きをするか試してみて下さい。
http://localhost:53280/Abc http://localhost:53280/Abc/Def http://localhost:53280/Abc/Def/12 http://localhost:53280/aBc/dEF/X9876
ちなみに Def() メソッド内で View("Index") とすれば、Def.cshtml を作らなくてもOKです。
パラメータの割り当ては「モデルバインダ」がやってくれる
さて Def() メソッドの引数「id」ですが、URLで与えられたパラメータが変換されて渡されます。型とかあまり深く考えなくても自動的に変換してくれます。
例えば、
public ActionResult Def(string id)
のところは、
public ActionResult Def(int? id)
としてもよいです。
パラメータを整数値として受け取ることができます。int? としているのは、パラメータを省略可能だからです。
URLのクエリ文字列だけでなく、フォームパラメータをメソッド引数に割り当てるようなことも可能です。これは ASP.NET MVC の強力なモデルバインダの機能で実現されています。
ファイルアップロードとかも対応してます。
詳しくは「モデルバインダ」でググるとたくさん情報が得られますよ。