Post Redirect Get パターン
フォームを送信(HTTPPost
)後に、ページを再読み込みするとフォームのデータが二重送信されてしまいます。
送信後しばらくたってページ再読込して表示を最新にしたいときなどに起こりがちです。
ブラウザのリロードボタンを押すと...
ASP.NET Core MVC ではPOST
リクエストに対しビューを返していると上記の問題が起こります。
[HttpPost] public IActionResult Edit(EditViewModel vm) {
if (ModelState.IsValid) {
/** データベースへの登録処理とか */
}
return View(); // ビューをそのまま返している
}
これはPOST
リクエストをGET
リクエストにリダイレクトしてページを再表示することで回避できます。
そのため Post-Redirect-Get パターンと呼ばれます。
サンプルプロジェクト
Post-Redirect-Get パターン の適用前
DemoController.cs
using Microsoft.AspNetCore.Mvc;
using PostRedirectGet.ViewModels.Demo;
namespace PostRedirectGet.Controllers {
public class DemoController : Controller {
// 画面表示時に呼ばれる
[HttpGet] public IActionResult Edit() => View();
// フォームの送信で呼ばれる
[HttpPost] public IActionResult Edit(EditViewModel vm) {
if (ModelState.IsValid) {
/** データベースへの登録処理とか */
}
return View();
}
}
}
Edit.cshtml
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@model PostRedirectGet.ViewModels.Demo.EditViewModel
@{ ViewData["Title"] = "Some Page"; }
<div class="text-center">
<h1 class="display-4">Psot-Redirect-Get Pattern</h1>
<form asp-controller="Demo" method="post">
New Email: <input asp-for="Email" />
<button type="submit">Register</button>
</form>
</div>
EditViewModel.cs
using System.ComponentModel.DataAnnotations;
namespace PostRedirectGet.ViewModels.Demo {
public class EditViewModel {
[Required, EmailAddress] public string Email { get; set; }
}
}
Post-Redirect-Get パターンの適用後
画面表示時のHTTPGet
へリダイレクトするだけです。
DemoController.cs
public class DemoController : Controller {
+ // 初期表示時とフォーム送信後に呼ばれる
[HttpGet] public IActionResult Edit() => View();
[HttpPost] public IActionResult Edit(EditViewModel vm) {
if (ModelState.IsValid) {
/** データベースへの登録処理とか */
}
- return View();
+ // [HttpGet] public IActionResult Edit() へリダイレクトする
+ return RedirectToAction(nameof(Edit));
}
}
これでフォーム送信後にページを更新しても二重送信されなくなりました。
備考
プロジェクト構成は下記のとおりです。
.
|-- Controllers
| `-- DemoController.cs
|-- PostRedirectGet.csproj
|-- Program.cs
|-- Properties
| `-- launchSettings.json
|-- Startup.cs
|-- ViewModels
| `-- Demo
| `-- EditViewModel.cs
|-- Views
| `-- Demo
| `-- Edit.cshtml
|-- appsettings.Development.json
|-- appsettings.json
|-- bin
|-- obj
`-- wwwroot
.NET Core SDK のバージョンは 3.0.100 、C# の言語バージョンは 8.0 で作業しました。
$ dotnet --version
3.0.100