情報応用演習Ⅰ(2024)

【T5b】モデルとデータベースの連携(後編)(5/8)

プロジェクトタイプ(注意: 本文参照)
プロジェクト名T5b
ソリューション名PIT5
注意
  • 本ページの作業内容は 前のページまでの続き になっていることに注意せよ.
    • 先に前のページまでをすべて読み,指示されている作業を済ませてから本ページを読むこと.
    • プロジェクトの作成作業については準備作業を参照せよ.

5b-5. Createアクションとビューの作成

このままでは何も表示されないので,まず学生を登録するためのフォームを追加しよう. StudentsControllerクラスに_に示すメソッドを追加する.

StudentsControllerクラスの変更内容(Createアクション(GET用))
1
2
3
4
5
// Createアクション(GET用)
public IActionResult Create() 
{
    return View(new Student());
}

ここでは単にView()メソッドの呼び出しを含むのみである.このCreateアクションでは Studentクラスをモデルクラスとして編集を行うため,View()メソッドにStudentクラスの インスタンスをデフォルトコンストラクタで生成して渡している. このアクションに対応するビューを作成しよう. Views/Students フォルダにCreateという名前のビューを追加する. Views/Students/Create.cshtml を_のように変更する.

Views/Students/Create.cshtmlの変更内容
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
@model Student
 
@{
    ViewData["Title"] = "新規学生の登録";
 
    if (Model is null) throw new ArgumentNullException(nameof(Model)); // ad-hoc! 非null保証のための回避策
}
 
<form asp-action="Create">
    @* 姓(LastName) のための入力欄 *@
    <label asp-for="@Model.LastName"></label>:
    <input asp-for="@Model.LastName" />
    <span asp-validation-for="@Model.LastName"></span>
    <br />
 
    @* 名(FirstName) のための入力欄 *@
    <label asp-for="@Model.FirstName"></label>:
    <input asp-for="@Model.FirstName" />
    <span asp-validation-for="@Model.FirstName"></span>
    <br />
 
    @* 性別(Sex) のための入力欄 *@
    <label asp-for="@Model.Sex"></label>:
    <select asp-for="@Model.Sex" asp-items="Html.GetEnumSelectList<SexType>()" ></select>
    <span asp-validation-for="@Model.Sex"></span>
    <br />
 
    @* 電話番号(PhoneNumber) のための入力欄 *@
    <label asp-for="@Model.PhoneNumber"></label>:
    <input asp-for="@Model.PhoneNumber" />
    <span asp-validation-for="@Model.PhoneNumber"></span>
    <br />
 
    @* メールアドレス(Mail) のための入力欄 *@
    <label asp-for="@Model.Mail"></label>:
    <input asp-for="@Model.Mail"/>
    <span asp-validation-for="@Model.Mail"></span>
    <br />
 
    @* 誕生日(Birthday) のための入力欄 *@
    <label asp-for="@Model.Birthday"></label>:
    <input asp-for="@Model.Birthday" />
    <span asp-validation-for="@Model.Birthday"></span>
    <br />

    <input type="submit" value="送信" />
</form>
 
<a asp-action="Index">一覧に戻る</a>
 
@section Scripts
{
    @{ await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

ここでは「性別」を入力するための select 要素(24行目)を除けば特段目新しい機能は使用していない. select 要素はたいていはドロップダウンリストとして表示されるHTMLの要素である. 素のHTMLでは select 要素の選択肢は,この要素内に option 要素を置くことで用意するが, ここでは asp-items タグヘルパーを用いて選択肢を用意している. StudentSexプロパティはSexType列挙型(リスト5a-3)のプロパティであるため, その入力値はこの列挙型のいずれかの値でなければならない.そのため select 要素の選択肢も これらに対応する値である必要があるが, asp-items タグヘルパーを使用することでこの列挙型に対応する 選択肢を自動的に生成することができる.

次にこのフォームの送信に対応するアクションメソッドを用意しよう. StudentsControllerクラスに_に示すメソッドを追加する.

StudentsControllerクラスの変更内容(Createアクション(POST用))
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
// Createアクション(POST用)
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create([Bind("FirstName, LastName, Sex, PhoneNumber, Mail, Birthday")]Student student) 
{
    if (ModelState.IsValid)                        // 入力値に誤りがない場合のみデータベースへの登録処理を行う.
    {
        student.Registered = DateTime.Now;         // 登録日時を設定する.

        _context.Add(student);                     // 新たな学生情報をデータベースに追加する.
        _context.SaveChanges();                    // データベースに変更を保存する.

        return RedirectToAction(nameof(Index));    // 設計では Details に遷移させる予定だが,
                                                   // まだ作成していないのでとりあえず Index に遷移させる.
    }
    else 
    {
        return View(student);
    }
}

メソッドの引数の型が今回作成したモデルクラスであるStudentクラスとなっている点は以前のチュートリアルと同様だが, 今回は引数に[Bind]属性を適用している点が異なる.これは_で用意したフォームでは 姓(FirstName),名(LastName),姓別(Sex),電話番号(PhoneNumber),メールアドレス(Mail),誕生日(Birthday)しか入力させていないためである. このようにフォームでモデルクラスの一部のプロパティにしか値を設定しない場合には,[Bind]属性を用いて 反映させるプロパティ名を限定する

8行目ではその学生の登録日時をシステムの時計を使って設定している. 10~11行目ではフォームから受け取ったStudentクラスのオブジェクトをデータベースに追加し(Add()メソッド), その変更をデータベースに反映させている(SaveChanges()メソッド).これらに関しては チュートリアル【T2e】と同じである.

return 文ではIndexアクションに遷移するように指定している. RedirectToAction()メソッドは,別のアクションメソッドを呼び出すためのメソッドである. 引数にアクションメソッドの名前を文字列として渡すことで,指定したアクションが呼び出される. なお,nameof式は, 渡されたクラスやメンバーの識別子(=名前)を文字列として取り出すための式である.

ここまで書けたら実行してみよう.「新規作成」のリンクをクリックしてCreateアクションにアクセスしてみよう. _のようなフォームが表示されるはずである.ここで前節で 設定したモデルクラスの各プロパティへの注釈がどのようにフォームに反映されているのかを確認してみよう. このための方法はいくつかあるが,今回は Firefox の 開発ツール を使用してみよう.

F12キーを押して開発ツールを起動し「インスペクター」を選択して,アイコンをクリックしてから, 各入力欄をクリックしてみよう.すると「インスペクター」で選択した要素に対応するHTMLの記述がハイライトされる(_). ここで input 要素の type 属性に注目しよう.input要素のtype属性は 「【T3b】POSTを処理する」でも少し登場したが, その入力欄に入力するべき内容や表示方法に関する注釈を与えるものである.「姓(LastName)」や「名(FirstName)」の入力欄,つまり モデルクラスにおいては通常の string 型である入力欄は type 属性に"text"という設定値が指定されているはずである(_). これは「一行入力」を指向する入力欄であるとの指定で,最も汎用的な入力欄の設定である.一方,「電話番号(PhoneNumber)」や 「メールアドレス(Mail)」「誕生日(Birthday)」の入力欄の type 属性の設定値を確認してみよう.「電話番号」の入力欄には"tel", 「メールアドレス」の設定欄には"email",「誕生日」の入力欄には"date"が指定されているはずである.これらは各々,電話番号, メールアドレス,日付の入力のための入力欄であることを意味している(_).

実行結果

デスクトップ版のウェブブラウザでは,入力に対する特別な補助が確認できるのはtype="date"が指定されている「誕生日」の 入力欄だけであるが(_),スマートフォン版のウェブブラウザではtype="tel"の入力欄に対してはテンキーが表示されたり, type="email"の入力欄に対しては@マーク付きのフルキーボードが表示されるなどの補助が表示される(__). 注目するべきは,これらの入力欄の指定が_のRazorページの記述には全く含まれていない,ということである. これらの指定は,モデルクラスであるStudentクラスの各プロパティに対する注釈(≒属性の指定)によって行われている,ということを覚えておこう.

また,_の24行目で設定した select 要素(「性別」)の内容も確認しておこう.この入力欄は ドロップダウンリストとして描画されていることが分かるだろう.これは_で input 要素ではなく select 要素として記述したためであるが,asp-itemsヘルパーの指定によって選択肢を表す option 要素が, select 要素内に 生成されていることも確認しておこう.アイコンをクリックして「性別」のドロップダウンリストをクリックする. 「インスペクター」で select 要素の▶をクリックして展開すると,4つの option 要素が自動生成されていることが分かるだろう(_). このように「複数の選択肢の中から一つを選択する」必要がある項目は select 要素とasp-itemsタグヘルパーを使用して入力欄を 用意するということを覚えておこう.ここまでを確認したら Firefox の開発ツールは閉じでよい.

では,このフォームを使って実際に学生情報を登録してみよう.適当な学生情報を入力して「送信」をクリックしてみよう(_). 学生が登録されIndexアクションに遷移して,その情報が一覧に表示されるはずである(_) . 後の試行のために適当に2~3件追加しておこう (_). 「メールアドレス」や「誕生日」は今回は必須の項目ではないが後の確認のために数件はこれらの情報を設定した学生も登録しておこう

実行結果

実際にデータベースのテーブルにも新規レコードが作られていることを確認しておこう. pgAdmin で「 Servers 」→「 PostgreSQL 16 」→「 Databases 」に表示される データベースの一覧から 「 t5b_db 」を右クリックし「 Query Tool 」をクリックしてクエリツールを開き, Students テーブルのすべての内容を表示する SQL文を実行しよう.フォームで入力した内容のレコードが作成されていることが分かるはずである(_).

Last updated on 2024-05-10
Published on 2024-05-10

Powered by Hugo. Theme by TechDoc. Designed by Thingsym.