エンジニア初心者がC#/ASP.NETを学ぶ 仕事

ASP.NET Core MVC, Entity Framework Core 一覧表に登録・編集・削除機能を追加。完全ガイド!

カテゴリを登録するフォームを作成


Createメソッドを作成してからViewファイルを作成。


ビューファイル名はメソッド名と一致する必要があるので注意。
追加を押す。

return View(new Category);として新しいカテゴリーをビューに渡してもいいんだけど、何も渡さなくてもビューファイルで@model Categoryとカテゴリーを定義していれば新しいカテゴリーのオブジェクトが作成されるので問題ない。

@model Category

<div class="row pt-2">
    <div class="col-6">
        <h1>カテゴリー</h1>
    </div>
</div>
<form method="post">
    <div class="form-group">
        <label asp-for="Name"></label>
        <input asp-for="Name" class="form-control" placeholder="カテゴリー名">
    </div>
    <div class="form-group mb-3">
        <label asp-for="DisplayOrder"></label>
        <input asp-for="DisplayOrder" class="form-control" placeholder="表示順序">
    </div>
    <button type="submit" class="btn btn-outline-primary">追加</button>
    <a asp-controller="Category" asp-action="Index" class="btn btn-secondary">一覧に戻る</a>
</form>

asp-forのInput Tag Helperにはカテゴリーモデルで定義されたプロパティしか指定できないので注意。
なので、例えばNameTestとするとエラーになる。

それとasp-forがあればタイプを定義する必要がなく、プロパティ名から自動的にタイプを検索する。


カテゴリーモデルのNameプロパティに[DisplayName("カテゴリー名")]のデータアノテーションを追加してビルドすれば、ラベルにカテゴリー名と表示できる。
追加しない場合はデフォルトではNameと表示される。

登録処理を作成

[HttpPost]
public IActionResult Create(Category obj) 
{ 
    _db.Categories.Add(obj);
    _db.SaveChanges();
    return RedirectToAction("Index","Category");
}


カテゴリーを追加したら、Indexメソッドにリダイレクトする。

バリデーションを作成


まずはサーバー側のバリデーションを追加していく。モデルにデータアノテーションを追加する。

条件分岐を追加してバリデーションに引っかかると、ModelState(Categoryオブジェクトのこと).IsValidがfalseになる。

モデルに定義したエラーメッセージを表示させるにはasp-validation-forを使う。

クライアント側のバリデーションを追加したい場合は、@Scriptsの処理を追加する。これを追加することによってエラーがある場合はクライアント側でエラーを表示してくれるので画面のリロードが実行されないで済む。

編集機能を作成


リンクを呼び出すときに、ID を渡すにするにはasp-route-idを使う。

public IActionResult Edit(int? id)
        {
            if (id == null || id == 0)
            {
                return NotFound();
            }
            Category? categoryFromDb = _db.Categories.Find(id);
            //Category? categoryFromDb1 = _db.Categories.FirstOrDefault(u=>u.Id==id);
            //Category? categoryFromDb2 = _db.Categories.Where(u=>u.Id==id).FirstOrDefault();


            if (categoryFromDb == null)
            {
                return NotFound();
            }
            return View(categoryFromDb);
        }

        [HttpPost]
        public IActionResult Edit(Category obj)
        {
            if (ModelState.IsValid)
            {
                _db.Categories.Update(obj);
                _db.SaveChanges();
                TempData["success"] = "更新しました";
                return RedirectToAction("Index");
            }
            return View();
        }


ここで大事なのはデータベースから編集したいレコードを取得し、それをビューに渡すこと。

@model Category

<div class="row pt-2">
    <div class="col-6">
        <h1>カテゴリー編集</h1>
    </div>
</div>
<form method="post">
    <div class="form-group">
        <label asp-for="Name"></label>
        <input asp-for="Name" class="form-control" placeholder="カテゴリー名">
        <span asp-validation-for="Name" class="text-danger"></span>
    </div>
    <div class="form-group mb-3">
        <label asp-for="DisplayOrder"></label>
        <input asp-for="DisplayOrder" class="form-control" placeholder="表示順序">
        <span asp-validation-for="DisplayOrder" class="text-danger"></span>
    </div>
    <button type="submit" class="btn btn-outline-success">編集</button>
    <a asp-controller="Category" asp-action="Index" class="btn btn-secondary">一覧に戻る</a>
</form>

@section Scripts{
    @{
        <partial name="_ValidationScriptsPartial" />
    }
}


データのIdを送信する以下のInputがないやんと気づいた人もいるかもしれないけど、これは必須ではない。
<input asp-for="Id" hidden />
じゃあどうやってどのIdのレコードを更新するのが分かるのっていう話なんだけど、↑がなくてもコントローラー側にポストされるオブジェクトにはちゃんとIdの値が含まれているみたい。

削除機能を作成

public IActionResult Delete(int? id)
{
    if (id == null || id == 0)
    {
        return NotFound();
    }
    Category? categoryFromDb = _db.Categories.Find(id);

    if (categoryFromDb == null)
    {
        return NotFound();
    }
    return View(categoryFromDb);
}

[HttpPost, ActionName("Delete")]
public IActionResult DeletePost(int? id)
{
    Category? obj = _db.Categories.Find(id);
    if (obj == null)
    {
        return NotFound();
    }
    _db.Categories.Remove(obj);
    _db.SaveChanges();
    TempData["success"] = "削除しました";
    return RedirectToAction("Index");
}


次に削除機能を追加していく。
アクションメソッドに同じ名前を付けてない理由はget と post でパラメータが同じの場合は同じメソッド名にできないみたい。だから、postの方はDeletePostという名前にする。

余談だがフォームで削除ボタン押したら処理の中で delete アクション メソッドが検索されるみたい。エンドポイントのアクション名が DeletePost になっているからフォームでDeletePostのアクション メソッドが実行されるように指定しなくてもDeletePostが実行されるようになってるみたい。

@model Category
<div class="row pt-2">
    <div class="col-6">
        <h1>カテゴリー削除
        </h1>
    </div>
</div>
<form method="post">
    <input asp-for="Id" hidden />
    <div class="form-group">
        <label asp-for="Name"></label>
        <input asp-for="Name" class="form-control" disabled placeholder="カテゴリー名">
    </div>
    <div class="form-group mb-3">
        <label asp-for="DisplayOrder"></label>
        <input asp-for="DisplayOrder" class="form-control" disabled placeholder="表示順序">
    </div>
    <button type="submit" class="btn btn-outline-danger">削除</button>
    <a asp-controller="Category" asp-action="Index" class="btn btn-secondary">一覧に戻る</a>
</form>

成果物

成果物は以下。


-エンジニア初心者がC#/ASP.NETを学ぶ, 仕事