ASP.NET Coreでリダイレクト先に値(メッセージ)を引き継ぐ - TempData の利用
質問: リダイレクト先のページに値を引き継ぎたい
Razor Pagesでアプリを作成しているのですが、検証処理をサーバー側で実施しています。
SubmitボタンをクリックするとPOSTで遷移して、検証する動作ですが、検証に失敗した場合にエラーメッセージを画面に表示します。
この時、OnPost() メソッド(あるいは OnPost*****()メソッド) で return Page(); すれば、ViewDataやBindPropertyのプロパティ値を画面に表示できますが、
元のページが動的ページのため、OnPost内にOnGetで実装されているページ読み込み処理を実装するのはちょっと良くないなと考えています。
そのため、リクエスト元のページにすぐにリダイレクトする構造にしようと考えています。
いわゆるPost-Redirect-Getモデル (PRGモデル)での実装です。
このとき、ViewDataやBindProtpertyの値が失われてしまうため、エラーメッセージを PRG先のページに伝えたいのですが、良い方法はありますか?
方針
リダイレクト先のページに値やメッセージを引き継ぐ方法として、ASP.NET Coreでは TempData機能が用意されています。
この記事では、TempData機能を利用した値の引継ぎ方法を紹介します。
プログラム
ASP.NET Core アプリケーションを作成して以下のコードを記述します。
namespace TempDataDemo
{
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
var app = builder.Build();
app.MapRazorPages();
app.MapGet("/", () => "Hello World!");
app.Run();
}
}
}
@page
@model TempDataDemo.Pages.SimpleTempDataModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
}
<html>
<head>
<title>TempData Demo</title>
</head>
<body>
<h1>TempData Demo</h1>
<form method="post">
<label for="input">入力:</label><br />
<input type="text" asp-for="InputValue" /><br />
<input type="submit" value="Submit" />
</form>
@if (Model.TempData["ErrorMessage"] != null) {
<h2>メッセージ:</h2>
<p>@Model.TempData["ErrorMessage"]</p>
}
</body>
</html>
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace TempDataDemo.Pages
{
public class SimpleTempDataModel : PageModel
{
[BindProperty]
public string InputValue { get; set; }
public void OnGet()
{
}
public IActionResult OnPost()
{
if (!int.TryParse(InputValue, out var iValue)) {
TempData["ErrorMessage"] = "数値を入力してください。";
}
else {
if (iValue <= 10) {
}
else {
TempData["ErrorMessage"] = "10以下の数値を入力してください。";
}
}
return RedirectToPage("/SimpleTempData");
}
}
}
実行結果
プロジェクトを実行します。Webブラウザで以下のパスにアクセスします。
(アプリケーションルートURL)/SimpleTempData
下図のページが表示されます。

テキストボックスに入力します。"8"を入力して[Submit]ボタンをクリックします。

元の画面に戻ります。メッセージは表示されません。

続いてテキストボックスに "200"を入力して、[Submit]ボタンをクリックします。

リダイレクトされ、同じページが表示されますが、[メッセージ]の項目が表示され、OnPostメソッドで設定した
"10以下の数値を入力してください。"のメッセージが表示されます。

テキストボックスに"Penguin"を入力して[Submit]ボタンをクリックします。

同じページにリダイレクトして、[メッセージ]の項目が表示され、OnPostメソッドで設定した
"数値を入力してください。"のメッセージが表示されます。

TempDataを利用して、リダイレクト先のページに値を引き継ぐ処理を実装できました。
プロパティをTempData化する
プロパティに[TempData]属性を追加すると、プロパティをTempDataと同様の振る舞いにできます。
以下のRazorPageを作成します。
@page
@model TempDataDemo.Pages.SimpleTempDataPropertyModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
}
<html>
<head>
<title>TempData Demo</title>
</head>
<body>
<h1>TempData Demo</h1>
<form method="post">
<label for="input">入力:</label><br />
<input type="text" asp-for="InputValue" /><br />
<input type="submit" value="Submit" />
</form>
@if (Model.ErrorMessage != "") {
<h2>メッセージ:</h2>
<p>@Model.ErrorMessage</p>
}
</body>
</html>
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace TempDataDemo.Pages
{
public class SimpleTempDataPropertyModel : PageModel
{
[BindProperty]
public string InputValue { get; set; }
[TempData]
public string ErrorMessage { get; set; }
public void OnGet()
{
}
public IActionResult OnPost(string inputValue)
{
if (inputValue.Length > 0 || inputValue[0] == 'p') {
}
else {
ErrorMessage = "先頭が 'p' で始まる文字列を入力してください。";
}
return RedirectToPage("/SimpleTempDataProperty");
}
}
}
解説
TempData属性を記述することで、ErrorMessage プロパティがTempDataと同様の動作になり、リダイレクト先のページで参照できる状態になります。
[TempData]
public string ErrorMessage { get; set; }
リダイレクトすると通常はプロパティの内容は失われますが、ErrorMessageプロパティは遷移前のページの値が保持されています。
@if (Model.ErrorMessage != "") {
<h2>メッセージ:</h2>
<p>@Model.ErrorMessage</p>
}
実行結果
プロジェクトを実行します。Webブラウザで以下のパスにアクセスします。
(アプリケーションルートURL)/SimpleTempDataProperty
下図のページが表示されます。

テキストボックスに "penguin" を入力し、[Submit]ボタンをクリックします。

ボタンをクリックするとPOST処理が実行され、そのあとリダイレクトにより元のページに戻ります。
メッセージ等表示されません。

続いてテキストボックスに"ducK"を入力し、[Submit]ボタンをクリックします。

POSTが実行され元のページにリダイレクトされます。今回はページ下部に[メッセージ]の枠が表示され、
サーバー側で設定した"先頭が'p'で始まる文字列を入力してください。"のメッセージが表示されます。

[TempData]属性を利用してプロパティをTempData化できました。
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用