Indexアクションの動きを見てみる
ここまでで、Scaffoldingによる「足あとアプリ」ができあがりました。ScaffoldingによってFootmarkControllerコントローラが作成され、たくさんのアクションメソッドとそれに対応するビューが作成されますが、モデルのあるアクションとビューの基本的な動きを理解するために、第5回と同様にIndexアクションに絞ってその動きを見ていきましょう。
コントローラ(Indexアクション) - Controllers/FootmarkController.csファイル
まずは、コントローラであるControllers/FootmarkController.csファイルを見てみましょう(リスト1)。
public class FootmarkController : Controller { …データベースコンテキストフィールドとコンストラクタは略… // Indexアクション(GET) public async Task<IActionResult> Index() (1) { return _context.Footmark != null ? (2) View(await _context.Footmark.ToListAsync()) : (3) Problem("Entity set 'MvcFootmarkContext.Footmark' is null."); (4) } …略… }
コントローラクラスの定義については、第5回で紹介したHomeコントローラと同様でControllerクラスを継承したものとなります。コンストラクタは、ロガークラス(ILogger)の注入ではなく、データベースコンテキスト(MvcFootmarkContext)の注入に変わっているのはRazor Pagesと同じです。
(1)以降が、Indexアクションメソッドの定義です。Indexアクションは、全てのモデルデータを取得し、ビューに引き渡します。なお第4回でも触れましたが、データベースが絡むなど比較的時間のかかる処理を含むときは、非同期実行が基本です。そのためメソッドにはasync演算子が指定されており、メソッドの戻り値もTask<IActionResult>型となります(HomeコントローラのIndexアクションメソッドではIActionResult型でした)。
(2)は、データセットであるFootmarkプロパティの有効と無効で処理を振り分けています。(3)有効(非null)であれば、await _context.Footmark.ToListAsync()の実行でモデルデータのリストが取得され、それがViewメソッドに渡されてViewResult型の戻り値となります。(4)無効(null)であれば、エラーメッセージを渡されたProblemメソッドの戻り値であるObjectResult型が戻り値となります。このObjectResult型も、ActionResult型を継承したクラスです。
ここでは、(3)のようにViewメソッドに引数があります。引数は、ToListAsyncメソッドの戻り値であるTask<List
構文 | メソッド |
---|---|
View() | 既定の動作 |
View(view) | ビュー名あるいはビューファイル名を渡す |
View(model) | モデルデータを渡す |
View(view, model) | ビュー名とモデルデータを渡す |
引数を持たない場合の動作については第5回で紹介しました。同様に、ビュー名を指定したときも、「/Views/コントローラー名」→「/Views/Shared」の順で指定のビューが検索されます。ただしパスや拡張子を含んだファイル名であるときは、そのファイルをビューと見なします。モデルデータを渡すときには、Viewメソッドの引数に加えるほか、次のビューにおいても、それを受け取る指定が必要なのは第5回で触れた通りです。
ビュー(Indexアクション) - Views/Footmark/Index.cshtmlファイル
Indexアクションでは、全てのモデルデータを取得してビューに引き渡しました。次は、モデルデータを受け取る側のビューについて見てみましょう(リスト2)。
…中略… <table class="table"> …中略… <tbody> @foreach (var item in Model) { (2) <tr> <td> @Html.DisplayFor(modelItem => item.YourName) (3) </td> …中略… </tr> } </tbody> </table>
ビューの基本的な構造は第5回で紹介したViews/Home/Index.cshtmlと同様です。異なるのは、モデルデータを取り扱うため、@modelディレクティブを含む点です。
(1)は、モデルデータ(Viewメソッドで渡されたオブジェクト)の型の宣言です。ビューが受け取るモデルデータの型を明確にしておくことで、ビューにおいて静的な型チェックが利用できます。Razor Pagesではページモデル(PageModel)が渡されていましたが、ここではデータ型がIEnumerable<MvcSample.Models.Footmark>となっているように、ビューがモデルのコレクションを扱うことを宣言しています。コレクションなのは、Indexアクションが全てのモデルデータのリスト(この場合はTask<List>
(2)は、実際にModel変数にてモデルデータを参照しています。コレクションであるので、foreach文で要素数分だけ繰り返します。(3)で、個々の要素をDisplayForヘルパーにて表示しています。
このようにして、コントローラのIndexアクションから渡されたモデルデータのリストが表示されるというわけです。モデルであるFootmarkクラスのオブジェクトは単なる入れ物に過ぎず、コントローラのアクションメソッドが必要なデータ処理を行い、それをビューが表示するという役割分担ができています。
[NOTE]ViewModel
MVCにおいてビューが取り扱うモデルデータはViewModelと呼ばれています。Footmarkといったモデル内のデータの一部のみ必要な場合、あるいはそれ以外に渡すデータがある場合には、別にViewModelのクラスを作成し、それをビューに渡すことになります。第5回で紹介したErrorViewModelクラスも、まさにこのViewModelのために作られたクラスです。