第2回 スキャフォールディング機能で軽々DB連携アプリケーション:連載:ASP.NET MVC入門(5/5 ページ)
ASP.NET MVCの持つ自動生成機能を使って、データベース連携アプリを作成する。ASP.NET MVCの素晴らしさを実感できる機能だ。
6. Editアクション・メソッド&ビューを定義する
最後に、既存の書籍情報を更新するための編集画面(アクション・メソッドとビュー)を作成しよう。ビューの作成に必要な情報を以下に。
項目 | 設定値 |
---|---|
View name | Edit |
Create a partial view(.ascx) | チェックしない |
Create a strongly-typed view | チェックする |
View data class | MvcApp.Book(VBの場合) MvcAppCs.Models.Book(C#の場合) |
View content | Edit |
Select master page | チェックしない |
表7 [Add View]ダイアログの設定値 |
自動生成されたコードを基に、必要な個所を追記/修正したのが以下のコードである(追記/修正した部分は太字で示している)。先ほど同様、ここでは入力値の検証処理については割愛しているので、注意してほしい。
//
// GET: /Book/Edit/5
// 初回アクセス時に呼び出される
public ActionResult Edit(string id) {
// bookテーブルから引数id(ISBNコード)に合致するレコードを取得
var books = from b in _db.Book
where b.isbn == id
select b;
// 戻り値はリストであるので、その先頭オブジェクトを取得
return View(books.First());
}
//
// POST: /Book/Edit/5
// [更新]ボタンクリックのタイミングで呼び出される
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(string id, FormCollection collection) {
try {
// bookテーブルから引数id(ISBNコード)に合致するレコードを取得
var book = (from b in _db.Book
where b.isbn == id
select b).First();
// 入力値を基にBookオブジェクトを更新&保存
UpdateModel(book);
_db.SaveChanges();
// 処理後はIndexアクションにリダイレクト
return RedirectToAction("Index");
} catch {
// 処理に失敗した場合にはEdit.aspxを再描画
return View();
}
}
'
' GET: /Book/Edit/5
' 初回アクセス時に呼び出される
Function Edit(ByVal id As String) As ActionResult
' bookテーブルから引数id(ISBNコード)に合致するレコードを取得
Dim books = From b In _db.Book _
Where b.isbn = id _
Select b
' 戻り値はリストであるので、その先頭オブジェクトを取得
Return View(books.First())
End Function
'
' POST: /Book/Edit/5
' [更新]ボタンクリックのタイミングで呼び出される
<AcceptVerbs(HttpVerbs.Post)> _
Function Edit(ByVal id As String, ByVal collection As FormCollection) As ActionResult
Try
' bookテーブルから引数id(ISBNコード)に合致するレコードを取得
Dim book = (From b In _db.Book _
Where b.isbn = id _
Select b).First()
' 入力値を基にBookオブジェクトを更新&保存
UpdateModel(book)
_db.SaveChanges()
' 処理後はIndexアクションにリダイレクト
Return RedirectToAction("Index")
Catch
' 処理に失敗した場合にはEdit.aspxを再描画
Return View()
End Try
End Function
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<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>
<link rel="Stylesheet" type="text/css"
href="../../Content/MyApp.css"/>
</head>
<body>
<%= Html.ValidationSummary("以下のエラーが発生しました。")%>
<% using (Html.BeginForm()) {%>
<fieldset>
<legend>書籍情報</legend>
<p>
<label for="isbn">ISBNコード:</label>
<%= Html.Encode(Model.isbn) %>
<%= Html.ValidationMessage("isbn", "*") %>
</p>
<p>
<label for="title">書名:</label>
<%= Html.TextBox("title", Model.title) %>
<%= Html.ValidationMessage("title", "*") %>
</p>
<p>
<label for="price">価格:</label>
<%= Html.TextBox("price", Model.price) %>
<%= Html.ValidationMessage("price", "*") %>
</p>
<p>
<label for="publish">出版社:</label>
<%= Html.TextBox("publish", Model.publish) %>
<%= Html.ValidationMessage("publish", "*") %>
</p>
<p>
<label for="published">刊行日:</label>
<%= Html.TextBox("published", String.Format("{0:d}", Model.published)) %>
<%= Html.ValidationMessage("published", "*") %>
</p>
<p>
<input type="submit" value="更新" />
</p>
</fieldset>
<% } %>
<div>
<%=Html.ActionLink("一覧へ戻る", "Index") %>
</div>
</body>
</html>
<%@ Page Language="VB" Inherits="System.Web.Mvc.ViewPage(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>
<link rel="Stylesheet" type="text/css"
href="../../Content/MyApp.css"/>
</head>
<body>
<%=Html.ValidationSummary("以下のエラーが発生しました。")%>
<% Using Html.BeginForm() %>
<fieldset>
<legend>書籍情報</legend>
<p>
<label for="isbn">ISBNコード:</label>
<%= Html.Encode(Model.isbn) %>
<%= Html.ValidationMessage("isbn", "*") %>
</p>
<p>
<label for="title">書名:</label>
<%= Html.TextBox("title", Model.title) %>
<%= Html.ValidationMessage("title", "*") %>
</p>
<p>
<label for="price">価格:</label>
<%= Html.TextBox("price", Model.price) %>
<%= Html.ValidationMessage("price", "*") %>
</p>
<p>
<label for="publish">出版社:</label>
<%= Html.TextBox("publish", Model.publish) %>
<%= Html.ValidationMessage("publish", "*") %>
</p>
<p>
<label for="published">刊行日:</label>
<%= Html.TextBox("published", String.Format("{0:d}", Model.published)) %>
<%= Html.ValidationMessage("published", "*") %>
</p>
<p>
<input type="submit" value="更新" />
</p>
</fieldset>
<% End Using %>
<div>
<%=Html.ActionLink("一覧へ戻る", "Index") %>
</div>
</body>
</html>
ここで注目していただきたいポイントは、次の点である。
(1)主キー項目は固定テキストに置き換える
まずは、簡単なビューの方から。スキャフォールディング機能では、Bookテーブル(オブジェクト)のすべての項目がテキストボックスとして展開されるが、唯一、isbnフィールドだけでは固定テキストで置き換えておくべきだ。isbnフィールドは、Bookテーブルの主キー項目であり、編集時に勝手に変更されてしまうのは好ましくないためだ。
(2)既存データの変更にはUpdateModelメソッドを使用する
先ほど、Createアクション・メソッドのところでも解説した入力値の自動バインド機能は便利な機能だ。しかし、この方法は新規レコードを追加するケースでしか利用できない。
既存のレコードを変更したい今回のようなケースでは、UpdateModelメソッドを使用する必要がある。UpdateModelメソッドは、指定されたオブジェクトに対して入力値をバインドするための機能を提供する*5。この場合、あらかじめLINQ to Entitiesで抽出したBookオブジェクトを指定しているので、このBookオブジェクトに対して、それぞれisbnプロパティには入力要素isbnの値が、titleプロパティには入力要素titleの値が、割り当てられることになるわけだ。
*5 ちなみに、類似の機能を持つメソッドとしてTryUpdateModelメソッドも用意されている。両者の機能はほぼ同様であるが、唯一、バインドに失敗した場合の挙動が異なる。バインドに失敗したとき、UpdateModelメソッドが例外を発生するのに対して、TryUpdateModelメソッドはfalse値を返す。例外処理の必要性に応じて使い分けるとよいだろう。
UpdateModelメソッドによって更新されたオブジェクトは、SaveChangesメソッドを呼び出すことでデータベースに反映される。Entity Frameworkを介したデータの更新処理については、前述の別稿が詳しいので、併せて参照されたい。
ここでは、先ほどのCreateアクションと同様、データの更新に成功した場合にはIndexアクションにリダイレクトし、失敗した場合には元のEdit.aspxを再描画している。
最後に、編集画面の動作を確認しておこう。編集画面は先ほどの一覧画面を立ち上げたうえで、一覧表の適当な行から[編集]リンクをクリックすることで呼び出すことができる。クリックした行に応じて、以下のような編集ビューが生成されれば成功である。適当にデータを更新すると、一覧画面の方でもその変更が反映されることも確認しておこう。
以上、今回はモデルを含めたコーディングの流れを理解するとともに、Visual Studioが提供するスキャフォールディング機能について解説した。
こうして文章にしてしまうと遠回りに思われるかもしれないが、実際に手を動かしてみると、ごく簡単な(しかもほとんど繰り返しの)手順で、一覧、登録、更新といった定型的な機能を持ったアプリケーションを作成できることがお分かりになるはずだ。これを機会に、皆さんの環境にもASP.NET MVCを導入し、ぜひ、その便利さを体感してみていただきたい。
Copyright© Digital Advantage Corp. All Rights Reserved.