まずは、Bookテーブルの一覧を定義するIndexアクションと、対応するビューから見ていこう。
■Indexアクション・メソッド
Indexアクション・メソッドのコードは次のようになる。追記部分は、太字で表している。
using MvcAppCs.Models;
MyMvcEntities _db = new MyMvcEntities();
//
// GET: /Book/
public ActionResult Index() {
// Bookテーブルからすべてのレコードを取得
var books = from b in _db.Book select b;
// 取得したオブジェクト(リスト)をビュー(Index.aspx)に引き渡す
return View(books);
}
Private _db As New MyMvcEntities()
' GET: /Book/
Function Index() As ActionResult
' Bookテーブルからすべてのレコードを取得
Dim books = From b In _db.Book Select b
' 取得したオブジェクト(リスト)をビュー(Index.aspx)に引き渡す
Return View(books)
End Function
ここでは、Entity Dataモデルに対して、LINQ to Entitiesを利用してクエリを発行している。LINQ to Entitiesについては別稿「.NETの新データアクセス・テクノロジADO.NET Entity Framework」の4ページ目を参照いただくとして、ここではBookテーブルの内容を無条件にすべて取り出しているとだけ理解しておこう。
ここで注目すべきは、LINQ to Entitiesによって取得したデータを、Viewメソッドに渡しているという点だ。前回も紹介したように、Viewメソッドの引数に何も指定しなかった場合、コントローラ・クラスは対応するビュー(この場合は「Book/Index.aspx」)を呼び出す。また、Viewメソッドに文字列を指定した場合には、指定されたビューを呼び出すことができるのだった。
そして、今回のようにViewメソッドにオブジェクト(モデル)を指定した場合には、ビューにそのオブジェクトを引き渡すことができる。この構文は、モデルと連携したアクションではよく利用するものなので、ここできちんと押さえておきたいところだ。
ちなみに、ビュー名とオブジェクトとを同時に指定したい場合には、以下のように記述すればよい(以下はVBのコード)。
Return View("Result", books)
■Book/Indexビュー
Indexアクションに対応するビューを作成するには、コード・エディタ上でアクション・メソッドにカーソルを合わせた状態でマウスを右クリックし、表示されたコンテキスト・メニューから[Add View]を選択すればよい。
上図のような[Add View]ダイアログが表示されるので、ここでは以下の表3の要領で必要な情報を入力する。
項目 | 設定値 |
---|---|
View name | Index |
Create a partial view(.ascx) | チェックしない |
Create a strongly-typed view | チェックする |
View data class | MvcApp.Book(VBの場合) MvcAppCs.Models.Book(C#の場合) |
View content | List |
Select master page | チェックしない |
表3 [Add View]ダイアログの設定値 |
[Create a strongly-typed view]は、直訳するならば「強く型付けされたビューを生成する」という意味だ。型付けというと難しくも聞こえるかもしれないが、要はモデル(Viewメソッドに渡したオブジェクト)をビューに関連付けるかどうかを決めるものだ。型付けを行うことで、モデルに含まれるデータ・フィールド(プロパティ)に対してもIntelliSense機能が働くようになる。本稿で扱うスキャフォールディング機能を利用するには、型付けは必ず有効にしておく必要がある。
型付けするデータ・クラス(モデル)は、[Add View]ダイアログの[View data class]で指定できる。ここでは、先ほどEntity Frameworkが自動生成したエンティティ「MvcApp.Book」を選択しておこう。これでデータベースから取り出されたBookオブジェクト(正確にはその集合)がビューに型付けされる。
後は、[View content]欄から自動生成するビューの種類を選択しておこう。ここでは「List」を選択したので、取り出したデータを一覧表示するためのビューが自動生成される。
ここでは、自動生成されたコードを基に、以下のようなコードを作成するものとする。変更しているのは太字の部分である。定型的な一覧表を作成するだけであれば、ごく最小限の修正で済んでしまうのが確認できるだろう。
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<IEnumerable<MvcAppCs.Models.Book>>" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>書籍一覧</title>
</head>
<body>
<p>
<%= Html.ActionLink("新規作成", "Create") %>
</p>
<table border="1">
<tr>
<th></th>
<th>
ISBNコード
</th>
<th>
書名
</th>
<th>
価格
</th>
<th>
出版社
</th>
<th>
刊行日
</th>
</tr>
<% foreach (var item in Model) { %> (1)
<tr>
<td>
<%= Html.ActionLink("編集", "Edit", new { id=item.isbn }) %> | (2)
<%= Html.ActionLink("詳細", "Details", new { id=item.isbn })%>
</td>
<td>
<%= Html.Encode(item.isbn) %>
</td>
<td>
<%= Html.Encode(item.title) %>
</td>
<td>
<%= Html.Encode(item.price.ToString("#,###円")) %>
</td>
<td>
<%= Html.Encode(item.publish) %>
</td>
<td>
<%= Html.Encode(String.Format("{0:D}", item.published)) %>
</td>
</tr>
<% } %>
</table>
</body>
</html>
<%@ Page Language="VB" Inherits="System.Web.Mvc.ViewPage(Of IEnumerable (Of MvcApp.Book))" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>書籍一覧</title>
</head>
<body>
<p>
<%=Html.ActionLink("新規作成", "Create")%>
</p>
<table border="1">
<tr>
<th></th>
<th>
ISBNコード
</th>
<th>
書名
</th>
<th>
価格
</th>
<th>
出版社
</th>
<th>
刊行日
</th>
</tr>
<% For Each item In Model%> (1)
<tr>
<td>
<%=Html.ActionLink("編集", "Edit", New With {.id = item.isbn})%> | (2)
<%=Html.ActionLink("詳細", "Details", New With {.id = item.isbn})%>
</td>
<td>
<%= Html.Encode(item.isbn) %>
</td>
<td>
<%= Html.Encode(item.title) %>
</td>
<td>
<%=Html.Encode(item.price.ToString("#,###円"))%>
</td>
<td>
<%= Html.Encode(item.publish) %>
</td>
<td>
<%=Html.Encode(String.Format("{0:D}", item.published))%>
</td>
</tr>
<% Next%>
</table>
</body>
</html>
このBook/Index.aspxの中で注目してほしいのは、次の点である。
(1)Viewメソッドに渡したオブジェクトはModelプロパティで取得できる
前述したように、アクション・メソッドでViewメソッドにオブジェクト(モデル)を渡した場合、そのオブジェクトはビューから参照できるようになる。具体的にBook/Index.aspxでオブジェクトを取得しているのは(1)のコードだ。
アクション・メソッドでは、Bookオブジェクトのリスト(IEnumerable(Of MvcApp.Book)オブジェクト)がセットされているはずなので、ここではFor Each命令で順にBookオブジェクト(変数item)を取り出し、その内容を出力しているわけだ。For Eachブロックの中では「item.isbn」のような形式で、各オブジェクトのプロパティにアクセスできる。
(2)ハイパーリンクを生成する
ハイパーリンクを生成するのは、HTMLヘルパーの1つであるActionLinkメソッドの役割だ。ActionLinkメソッドの主な構文は、次のとおり。
ActionLink (linkText As String, actionName As String [,routeValues As Object])
' linkText:リンクテキスト
' actionName:アクション名
' routeValues:ルーティング・ルールに引き渡すパラメータ
引数routeValuesには、ルーティングで使用するパラメータ値を匿名オブジェクトで指定する。前回記事の「ルーティングの設定を理解する」と併せて確認すると分かるように、デフォルトのルーティング・ルールでは「{id}」というパラメータが定義されている。
リスト3の(2)では、匿名型でidプロパティを指定することで、{id}パラメータに対してキーとなる値(ここではBookオブジェクトのisbnプロパティ)をセットしているわけだ。複数のパラメータを指定したい場合には、同じ要領で必要な数だけ、対応するプロパティを指定すればよい。
(2)のコードによって、具体的には以下のような<a>タグが生成される(isbnフィールドの値が「978-4-7980-1616-0」の場合)。
<a href="/Book/Edit/978-4-7980-1616-0">編集</a>
ちなみに、パラメータ情報が不要である場合には、以下のように引数routeValuesの指定を省略しても構わない。
<%=Html.ActionLink("新規作成", "Create")%>
ここまでの内容が確認できたら、まずは書籍一覧ページの挙動を確認してみよう。
書籍一覧ページには、以下のようなURLでアクセスできる(ただし、ポート番号は環境によって異なる可能性がある)。
http://localhost:3568/Book/Index *1
*1 「http://localhost:3568/Book」としても構わない。デフォルトのルーティング・ルールではアクション名のデフォルトは「Index」と指定されているからだ。
そして、次の図7のように、Bookテーブルに登録された書籍情報がテーブル表示されれば正しく動作している。
どうだろう。スキャフォールディング機能を利用することで、これだけの機能が、わずかにIndexアクションに数行のコードを追記し、Book/Index.aspxを数カ所修正するだけで実現できてしまった(日本語化の必要がなければ、実は、ビューにはまったく手を入れる必要はない)。慣れてしまえば、定型的な画面であれば恐らく数分程度で作成できてしまうはずだ。
Copyright© Digital Advantage Corp. All Rights Reserved.