しばやん雑記

Azure とメイドさんが大好きなフリーランスのプログラマーのブログ

ASP.NET MVC 3 開発入門 (14) - ビューの実装 (Create, Edit アクション)

ASP.NET MVC 3 開発入門 - インデックス

前回で Details アクションのビューを作成したので、今回は Create, Edit アクションのビューを実装していきます。Details アクションではモデルの表示しか行いませんでしたが、Create, Edit アクションではフォームが存在しているので入力検証を行う必要が出てきます。

入力検証は非常に面倒に感じると思いますが、ASP.NET MVC に標準で備わっている機能ですので簡単に実装できます。ちゃんと専用の HTML ヘルパーも用意されています。

それでは Create アクションのビューから実装していきたいと思います。まずはスキャフォールディングで生成されたコードを確認してみましょう。

@model MvcVideo.Models.Video

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Video</legend>

        <div class="editor-label">
            @Html.LabelFor(model => model.Title)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Title)
            @Html.ValidationMessageFor(model => model.Title)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Description)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Description)
            @Html.ValidationMessageFor(model => model.Description)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.CreatedAt)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.CreatedAt)
            @Html.ValidationMessageFor(model => model.CreatedAt)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.UpdatedAt)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.UpdatedAt)
            @Html.ValidationMessageFor(model => model.UpdatedAt)
        </div>

        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

MVC 3 のスキャフォールディングは賢くなっているので、プライマリキーのフォームは自動生成されないようになっています。しかし、それ以外の入力可否は分かりませんので修正しましょう。

例えば CreatedAt と UpdatedAt はアクションで値をセットするので不要ですね。そして動画アップロードを行うフォームが存在していないので、今回は仕方がないので手入力しましょう。

<div class="editor-label">
    動画ファイル
</div>
<div class="editor-field">
    <input type="file" name="File" />
    @Html.ValidationMessage("File")
</div>

非常に不格好ですが、MVC 3 標準ではファイルアップロードの HTML ヘルパーが存在しないので目を瞑ります。ヘルパー使いたいという方は ASP.NET MVC 3 と File API を利用してアップロード前に検証を行う - しばやん雑記 で File ヘルパーを作っていますので、参考にしていただければと思います。

追記

大事なことを忘れていました。今回はファイルアップロードを行うのですが、そのためには form の enctype 属性に "multipart/form-data" を指定しなくてはいけません。form は BeginForm メソッドで生成しているので、引数で属性を指定してあげましょう。

@using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
...
}

actionName と controllerName に null を指定すると自分自身に向けてポストするようになるので、それを利用して手間を省いています。

デザインはさておき、この修正だけで動画の新規登録機能が動作するようになります。さっそく画面を確認してみましょう。

ちゃんとタイトル、説明、動画ファイルの 3 項目のフォームが表示されていますね。しかしフォームのラベルはどこから来たのでしょうか?ビューには

@Html.LabelFor(model => model.Title)

などとしか書いていませんよね。

ここでモデルを作成した時を思い出してください。あの時、プロパティに DisplayName 属性を付けたのですが、それを LabelFor が認識して表示されるようになっているのです。ちなみに DisplayName 属性を使うことで簡単に多言語対応を行うこともできます。

殆どスキャフォールディングで生成されたコードから変更していませんが、ちゃんとモデルにデータアノテーション属性で指定した通りに入力検証も行ってくれます。

ちゃんとファイルアップロードの検証も動作していますね。これで Create アクションのビューは完成しました。

それでは Edit アクションのビューも作成していくのですが、スキャフォールディングで作成されたコードを見ていただくと分かるように殆ど一緒です。違う点はプライマリキーの値を表示するコードが増えているだけです。

それでは Create と同じように CreatedAt と UpdateAt フォームの削除、そしてファイルアップロードのフォームを追加しましょう。これで Edit アクションのビューも完成です。

@model MvcVideo.Models.Video

@{
    ViewBag.Title = "Edit";
}

<h2>Edit</h2>

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

@using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" })) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Video</legend>

        @Html.HiddenFor(model => model.VideoId)

        <div class="editor-label">
            @Html.LabelFor(model => model.Title)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Title)
            @Html.ValidationMessageFor(model => model.Title)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Description)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Description)
            @Html.ValidationMessageFor(model => model.Description)
        </div>

        <div class="editor-label">
            動画ファイル
        </div>
        <div class="editor-field">
            <input type="file" name="File" />
            @Html.ValidationMessage("File")
        </div>

        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

今回で動画の新規登録と編集が出来るようになりました。それでは次回で Index, Delete アクションのビューを作成して動画周りを完成させてしまいましょう、お疲れ様でした。