SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

.NET最新版でASP.NET Core

.NET 6でASP.NET CoreのMVCアプリケーションのデータ処理を理解しよう

.NET最新版でASP.NET Core 第6回


  • X ポスト
  • このエントリーをはてなブックマークに追加

その他のアクションについても見てみる

 改めてFootmarkコントローラについて、他のアクションも見ていきましょう。アクションメソッドには、Index(GET)、Details(GET)、Create(GET、POST)、Edit(GET、POST)、Delete(GET、POST)の8個があります。HTTP GETで呼び出されるメソッドは表示系、HTTP POSTメソッドで呼び出されるメソッドは更新系です。表示系のIndexアクションを見てきましたので、ここからは更新系のCreateアクションを中心に見てみましょう。

コントローラ(Createアクション) - Controllers/FootmarkController.csファイル

 Controllers/FootmarkController.csファイルからCreateアクションのみを抜粋します(リスト3)。

リスト3:Controllers/FootmarkController.cs
// Createアクション(GET)
public IActionResult Create()	(1)
{
    return View();
}

// Createアクション(POST)
[HttpPost]				(2)
[ValidateAntiForgeryToken]		(3)
public async Task<IActionResult> Create([Bind("ID,YourName,Message,VisitTime")] Footmark footmark)		(4)
{
    if (ModelState.IsValid)	(5)
    {
        _context.Add(footmark);		(6)
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }
    return View(footmark);	(7)
}
…略…

 Createアクションのメソッドは、HTTP GETとPOSTで2つあります。このうちGETに対応するメソッドは、単にフォームを表示するだけなのでViewメソッドの呼び出しがあるのみです(1)。(4)はPOSTに対応する、すなわちフォームの送信で呼び出されるメソッドになります。Indexアクションと同様に非同期実行になります。短いコードですが、更新系のメソッドで重要な要素が多数盛り込まれています。

 (2)と(3)はアクションメソッドの属性です。HttpPost属性は、アクションメソッドがHTTP POSTに対するものであることを指定します。この属性のないメソッドは、HTTP GETに対するものとなります(HttpGet属性は既定値なので通常は記述しません)。(3)は、クロスサイトリクエストフォージェリ(CSRF)攻撃に対応するためのValidateAntiForgeryToken属性です。HTTP POSTのためのメソッドでは、この2つの属性がセットと言えるでしょう。

 後述しますが、method属性が"POST"であるフォームには自動的にCSRF攻撃対策用トークンが隠しフィールドとして埋め込まれ、フォームからそのまま送信されます。アプリケーション側は、フォームに埋め込んだトークンと送られてきたトークンを比較し、一致したときのみアクションを実行します(図4)。

図4:CSRF攻撃対策用トークンの働き
図4:CSRF攻撃対策用トークンの働き

 再び(4)ですが、特徴的な構文となっています。引数Footmarkはモデルオブジェクトですが、Bind属性が付加されています。この属性は、メソッドが受け入れるモデルのプロパティを列挙したもので、それ以外のプロパティが送られてきてもモデルにバインドしないことを意味します(オーバーポスティング攻撃対策)。フォームによって更新されないフィールドなど、送信されるべきでないプロパティをバインドしない指定をすることで、改ざんされたPOSTデータによる攻撃を防ぐことができます(図5)。この場合はFootmarkモデルの全てのプロパティが列挙されているので、これらを全て受け入れます。

図5:Bind属性によるオーバーポスティング攻撃対策
図5:Bind属性によるオーバーポスティング攻撃対策

 (5)は、フォームの送信で呼び出されるメソッドで必要な構文です。IsValidメソッドは、送信されてきたデータが検証(バリデーション)を通過したときにtrueになります。そうでないときはfalseになるので、そのまま(7)のようにモデルデータをViewメソッドの引数に与えて、自ら(フォーム)を再表示します。

 バリデーションを通過したときには、(6)からの処理を順番に実行します。Addメソッドでモデルデータをデータベースコンテキストに書き込み、SaveChangesAsyncメソッドで非同期にデータベースに反映します。最後は、RedirectToActionメソッドでIndexアクションにリダイレクトします。なお、RedirectToActionメソッドの戻り値はRedirectToRouteResult型で、ActionResult型を継承するクラスです。

ビュー(Createアクション) - Views/Footmark/Create.cshtmlファイル

 ビューのファイルはViews/Footmark/Create.cshtmlファイルです(リスト04)。このビューは、HTTP GETとPOSTの双方のCreateアクションで呼び出されます。

リスト4:Views/Footmarks/Create.cshtml
@model RazorPagesSample.Models.Footmark		(1)
…略…
<div class="row">
    <div class="col-md-4">
        <!-- POSTメソッドでCreateアクションに送信するフォーム -->
        <form asp-action="Create">	(2)
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <!-- asp-forタグヘルパーにはフィールドのみを与える -->
                <label asp-for="YourName" class="control-label"></label>	(3)
                <input asp-for="YourName" class="form-control" />
                <span asp-validation-for="YourName" class="text-danger"></span>
            </div>
            …略…
        </form>
    </div>
</div>
…あとはRazor Pagesにおけるものと同じなので省略…

 Createアクションのビューはフォームです。初期状態のフォーム、あるいはフォームの送信でバリデーションに問題があった場合の再表示に使用されます。

 (1)は、Indexアクションのビューで触れたように、ビューに渡されるViewModelの型です。ここではFootmarkモデルが直接渡されています。なお、HTTP GETのCreateアクションではViewメソッドの引数は空でしたので、この場合ビューに渡されるViewModelはnullになります。

 (2)はフォームの開始です。Razor Pagesではaction属性がなく、method属性で"POST"が指定されているのみで、自分自身にポストバックするという動きでした。ここでは、asp-actionタグヘルパーにてCreateアクションを呼び出します。このとき、自動的にmethod属性に"POST"が指定されるので、今度はHTTP POSTのCreateメソッドが実行され、データが登録されます。CSRF攻撃対策用トークンも送信されます。

 (3)はフォーム要素とモデルの関連付けですが、Razor Pagesではページモデルが渡されているので、そのプロパティであるFootmarkを使ってフィールドを参照します。ここではFootmarkモデルそのものが渡されているので、フィールドを直接参照できます。なお、初期表示のフォームではViewModelはnullなので、asp-forヘルパーによる参照の結果はブランクになります。

コントローラ(その他) - Controllers/FootmarkController.csファイル

 最後に、その他のアクションで特徴的な構文を見てみます(リスト5)。

リスト5:Controllers/FootmarkController.cs
// Editアクション(POST)
public async Task<IActionResult> Edit(int id, [Bind("ID,YourName,Message,VisitTime")] Footmark footmark)
{
    …略…
        try	(1)
        {
            _context.Update(footmark);
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)	(1)
        {
            if (!FootmarkExists(footmark.ID))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }
    …略…
}
…略…
// Deleteアクション(POST)
[HttpPost, ActionName("Delete")]	(4)
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
…略…

 Editメソッドでは、Createメソッドにはなかったtry〜catch文があります(1)。これは、catchしている例外のDbUpdateConcurrencyExceptionから分かるように、同時にレコードを更新しようとした更新特有の状況に対処しています。例外のキャッチでレコードの存在をチェックし、見つからなければ更新できないとしてNotFound()メソッドの戻り値(ActionResult型を継承するNotFoundObjectResult型)を返します。見つかれば競合として例外をさらにスローします。

 (4)はHttpPost属性ですが、引数ActionNameが指定されています。この引数は、アクションメソッドの名前が実際のアクションと異なる場合に指定するものです。2つあるDeleteメソッドは引数が同じ、すなわちシグネチャが同一ということになるので、片方の名前を変えてあげる必要があるのです。このようなときに引数ActionNameを指定してアクション名としては同一となるようにします。

まとめ

 今回はASP.NET Core MVCのまとめとして、ScaffoldingによるCRUD機能の追加や、そのコンロトーラやビューの解説を行いました。作成されるソースコードはRazor Pagesに比べると若干複雑になりますが、基本的にシンプルな構成になっていることがお分かりいただけたのではないかと思います。次回は、同じくASP.NET CoreのサブフレームワークであるBlazorを紹介します。

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
.NET最新版でASP.NET Core連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 山内 直(WINGSプロジェクト ヤマウチ ナオ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook <個人紹介>WINGSプロジェクト所属のテクニカルライター。出版社を経てフリーランスとして独立。ライター、エディター、デベロッパー、講師業に従事。屋号は「たまデジ。」。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/16317 2023/05/26 17:15

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング