Part6 ASP.NET MVC Coreによるデータ更新アプリ

まず、Sample02ControllerとViewを追加します。

$ yo aspnet:MvcController Sample02Controller
$ mkdir Views/Sample02
$ yo aspnet:MvcView Sample02/ListAuthors
$ yo aspnet:MvcView Sample02/EditAuthors

著者一覧ページを作るためにViewModelを追加し、Contollerとビューを編集します。

ViewModels/AuthorOverviewListViewModel.cs

using AspNetCorehandson.Models;

namespace AspNetCorehandson.ViewModels
{
    public class AuthorOverviewListViewModel
    {
        public AuthorOverview[] Authors { get; set; }
    }
}

Sample02Controller

[HttpGet]
public ActionResult ListAuthors()
{
    using (var pubs = new PubsEntities())
    {
        var query = pubs.Authors
                    .Select(a => new AuthorOverview
                    {
                        AuthorId = a.AuthorId,
                        AuthorName = a.AuthorFirstName + " " + a.AuthorLastName,
                        Phone = a.Phone,
                        State = a.State,
                        Contract = a.Contract
                    });
        var vm = new AuthorOverviewListViewModel
        {
            Authors = query.ToArray()
        };
        return View(vm);
    }
}

ListAuthors.cshtml

@using AspNetCorehandson.ViewModels
@model AuthorOverviewListViewModel
@{
    ViewBag.Title = "編集対象の著者選択";
}

<h4>編集対象となる著者を選択してください。</h4>

@{
    if (Model.Authors != null)
    {
        var data = Model.Authors as IList<AuthorOverview>;
        <div class="table-responsive">
            <table class="table table-condensed table-striped table-hover">
                <thead>
                    <tr>
                        <th>著者ID</th>
                        <th>著者名</th>
                        <th>電話番号</th>
                        <th></th>
                        <th>契約有無</th>
                    </tr>
                </thead>
                <tbody>
                    @foreach (var a in data)
                    {
                        <tr>
                            <td><a href="/Sample02/EditAuthor/@a.AuthorId">@a.AuthorId</a></td>
                            <td>@a.AuthorName</td>
                            <td>@a.Phone</td>
                            <td>@a.State</td>
                            <td><input type="checkbox" disabled @(a.Contract ? "checked" : "") /></td>
                        </tr>
                    }
                </tbody>
            </table>
        </div>
    }
}

<hr />

<p>
    <a href="/">業務メニューに戻る</a>
</p>

次に編集ページを作成します。編集ページのViewModelはValidationの属性を追加しておきます。

using System.ComponentModel.DataAnnotations;

namespace AspNetCorehandson.ViewModels
{
    public class AuthorEditViewModel
    {
        public string AuthorId { get; set; }

        [Required(ErrorMessage = "著者名(名)は必須入力項目です。")]
        [RegularExpression(@"^[\u0020-\u007e]{1,20}$", ErrorMessage = "著者名(名)は半角 20 文字以内で指定してください。")]
        public string AuthorFirstName { get; set; }

        [Required(ErrorMessage = "著者名(姓)は必須入力項目です。")]
        [RegularExpression(@"^[\u0020-\u007e]{1,40}$", ErrorMessage = "著者名(姓)は半角 40 文字以内で指定してください。")]
        public string AuthorLastName { get; set; }

        [Required(ErrorMessage = "電話番号は必須入力項目です。")]
        [RegularExpression(@"^\d{3} \d{3}-\d{4}$", ErrorMessage = "電話番号は 012 345-6789 のような形式で指定してください。")]
        public string Phone { get; set; }

        [Required(ErrorMessage = "州は必須入力項目です。")]
        [RegularExpression(@"^[A-Z]{2}$", ErrorMessage = "州は半角大文字 2 文字で指定してください。")]
        public string State { get; set; }
    }
}

Sample02Controller にHTTP GETのEditAuthorメソッドを追加します。これは編集画面を表示する際に呼ばれるアクションメソッドです。

[HttpGet]
public ActionResult EditAuthor(string id)
{
    // 当該著者 ID のデータを読み取る
    Author editAuthor = null;
    using (var pubs = new PubsEntities())
    {
        editAuthor = pubs.Authors.FirstOrDefault(a => a.AuthorId == id);
    }

    // View に引き渡すデータを準備する
    var vm = new AuthorEditViewModel()
    {
        AuthorId = editAuthor.AuthorId,
        AuthorFirstName = editAuthor.AuthorFirstName,
        AuthorLastName = editAuthor.AuthorLastName,
        Phone = editAuthor.Phone,
        State = editAuthor.State
    };

    // View にデータを引き渡すにあたり、入力データと周辺データを分けておく。
    // (ViewModel に周辺データを入れることで、ViewModel を完全にフォームモデルに一致させるように設計)
    using (var pubs = new PubsEntities())
    {
        var query = pubs.Authors.Select(a => a.State).Distinct();
        ViewData["AllStates"] = query.ToList();
    }

    return View(vm);
}

jQuery Validationを使うためのShared Viewを作成します。

Views/Shared/_ImportsLibraryValidation.cshtml

<script src="//ajax.aspnetcdn.com/ajax/jquery.validate/1.14.0/jquery.validate.min.js"></script>
<script src="//ajax.aspnetcdn.com/ajax/jquery.validate/1.14.0/localization/messages_ja.js"></script>
<script src="//ajax.aspnetcdn.com/ajax/mvc/5.2.3/jquery.validate.unobtrusive.min.js"></script>

Views/Shared/_ImportsStyleValidation.cshtml

<style type="text/css">
    @@media only screen and (min-width : 0px) and (max-width : 767px) {
    }


    @@media only screen and (min-width : 768px) and (max-width : 991px) {
        dl {
            width: 738px; /* 750-12 */
            margin: 6px;
        }


        dl dt {
            float: left;
        }


        dl dd {
            margin-left: 200px;
        }
    }


    @@media only screen and (min-width : 992px) and (max-width : 1199px) {
        dl {
            width: 958px; /* 970-12 */
            margin: 6px;
        }


        dl dt {
            float: left;
        }


        dl dd {
            margin-left: 200px;
        }
    }


    @@media only screen and (min-width : 1200px) {
        dl {
            width: 1158px; /* 1170-12 */
            margin: 6px;
        }


        dl dt {
            float: left;
        }


        dl dd {
            margin-left: 200px;
        }
    }


    /* エラーメッセージ用 */
    /* jQuery unobtrusive validation 用 */
    .field-validation-error {
        color: #ff0000;
    }


    .field-validation-valid {
        display: none;
    }


    .input-validation-error {
        border: 2px solid #ff0000;
        background-color: #ffeeee;
    }


    .validation-summary-errors {
        font-weight: bold;
        color: #ff0000;
    }


    .validation-summary-valid {
        display: none;
    }


    /* jQuery Validation 用 */
    .error { 
        color:red 
    }
    input.error, select.error, textarea.error {
        border: 2px solid red;
        background-color: #ffeeee;
    }


</style>

編集画面として、EditAuthor.cshtml を実装します。


@model AspNetCorehandson.ViewModels.AuthorEditViewModel
@{
    ViewBag.Title = "著者データの編集";
}
@section Libraries {
    @Html.Partial("_ImportsLibraryValidation")
}

@section Styles {
    @Html.Partial("_ImportsStyleValidation")
}

<h4>著者データを修正してください。</h4>

@using (Html.BeginForm("EditAuthor", "Sample02", new { id = Model.AuthorId }))
{
    <dl>
        <dt>著者ID</dt>
        <dd>@Model.AuthorId</dd>
    </dl>
    <dl>
        <dt>著者名(名)</dt>
        <dd>@Html.TextBoxFor(m => m.AuthorFirstName, new { data_val_specialnamecheck = "指定された名前(名・姓の組み合わせ)は使えません。" }) @Html.ValidationMessageFor(m => m.AuthorFirstName, "*")</dd>
    </dl>
    <dl>
        <dt>著者姓(姓)</dt>
        <dd>@Html.TextBoxFor(m => m.AuthorLastName, new { data_val_specialnamecheck = "指定された名前(名・姓の組み合わせ)は使えません。" }) @Html.ValidationMessageFor(m => m.AuthorLastName, "*")</dd>
    </dl>
    <dl>
        <dt>電話番号</dt>
        <dd>@Html.TextBoxFor(m => m.Phone) @Html.ValidationMessageFor(m => m.Phone, "*")</dd>
    </dl>
    <dl>
        <dt></dt>
        <dd>
            @{
                List<string> states = (List<string>)ViewData["AllStates"];
            }
            @Html.DropDownList("State", states.Select(s => new SelectListItem() { Text = s, Value = s, Selected = (s == Model.State) }))
        </dd>
    </dl>

    <p>
        <input type="submit" value="登録" />
        <input type="button" id="btnCancel" value="キャンセル" />
    </p>
    @Html.ValidationSummary("入力にエラーがあります。修正してください。")
}

<hr />

<p>
    <a href="/">業務メニューに戻る</a>
</p>


@section Scripts {

    <script type="text/javascript">
    $(function () {
        $("#btnCancel").click(function () {
            window.location = "@Url.Action("ListAuthors")";
            return false;
        });
    });
    </script>
}

Sample02Controllerに編集画面からPOSTされたときのアクションメソッドを実装します。

[HttpPost]
public ActionResult EditAuthor(string id, AuthorEditViewModel model)
{
    using (var pubs = new PubsEntities())
    {
        var query = pubs.Authors.Select(a => a.State).Distinct();
        ViewData["AllStates"] = query.ToList();
    }

    // 送信されてきたデータを再チェック
    if (ModelState.IsValid == false)
    {
        // 前画面を返す
        // ID フィールドがロストしているので補完する
        model.AuthorId = id;
        return View(model);
    }

    model.AuthorId = id;

    // データベースに登録を試みる
    using (var pubs = new PubsEntities())
    {
        var target = pubs.Authors.Where(a => a.AuthorId == model.AuthorId).FirstOrDefault();
        target.AuthorFirstName = model.AuthorFirstName;
        target.AuthorLastName = model.AuthorLastName;
        target.Phone = model.Phone;
        target.State = model.State;

        pubs.SaveChanges();
    }
    // 一覧画面に帰る
    return RedirectToAction("ListAuthors");
}

results matching ""

    No results matching ""