ASP.NET MVC TempData は”次のリクエスト”以降も参照できる
by 深夜連絡 ASP.NET MVC な Web アプリ Advent Calendar 2013 8 日目
前回 に引き続き TempData についてです。
ASP.NET MVC を始めたばかりの方にとっては、知らなくてもいい情報だと思います。そうでなくとも、通常の Web アプリ実装ではあまり使われないかもしれません。TempData の正体に興味がある方のみご覧ください。
TempData の正体
TempData は、現在と次のリクエスト間だけで使われることが多いですが、実は使い方次第で、次のリクエスト以降も値を取得できます。元はといえば「セッション状態(Session)」のラッパーライブラリだからです。
TempData には、以下のようなメソッドが用意されています。
- TempData["hoge"]
- TempData["hoge"] で値を取得すると、削除マークが付き、次回リクエスト以降は取得できない。
- TempData.Peek("key")
- TempData.Peek("key") で値を取得すると、削除マーク無しに値を取得できる。
- TempData.Keep()、TempData.Keep("key")
- TempData.Keep() を実行すると、次回も値を取得できるようになる。
つまり、TempData["hoge"] で値を取得しない限り、ずっと値は保存されているわけです。
また、TempData["hoge"] を使ったとしても、TempData.Keep(); を実行すれば値は保存されます。
こうなってくると本当に「セッション状態」(Session)と変わりありません。TempData として存在しうるそのアイデンティティーは、最初の説明通り「一時的な保存」でしょう。
上記の TempData の動作を検証するための、サンプルを実装し実際に確認してみます。
サンプル
概要
↓のように、GET リクエストを送信するリンクを5つ用意し、それぞれで値のセット、取得、Peek()、Keep()という TempData の操作を行います。TempData の値を取得できたとき、ビューに表示します。
TempData はリダイレクトの際によく使われますが、今回は単純に GET リクエストの連続で試してみます。
プロジェクトの用意
Visual Studio のサイト から、Visual Studio Express 2013 for Web(以下、VS Express 2013)をインストールします。
VS Express 2013 を開き、メニューから ファイル>新規作成>プロジェクト を選択します。
「ASP.NET Web アプリケーション」を選択し、OK します。
コントローラーを用意
↓のように HomeController を用意します。
HomeController.cs :
public class HomeController : Controller { // 1.メニューを表示するだけ [HttpGet] public ActionResult Menu() { return View("Menu"); } // 2.TempData に値をセット [HttpGet] public ActionResult InputTempData() { TempData["Food"] = "りんご"; return View("Menu"); } // 3.TempData の値を TempData["key"] で取得し表示します [HttpGet] public ActionResult GetTempData() { ViewBag.Food = TempData["Food"]; return View("Menu"); } // 4.TempData の値を Peek("key") で取得し表示します [HttpGet] public ActionResult PeekTempData() { ViewBag.Food = TempData.Peek("Food"); return View("Menu"); } // 5.TempData の値を TempData["key"] で取得し、Keep() を実行します [HttpGet] public ActionResult GetAndKeepTempData() { ViewBag.Food = TempData["Food"]; TempData.Keep(); return View("Menu"); } }
ビューの用意
~/Home/Menu.cshtml を用意します。
Menu.cshtml :
@{ ViewBag.Title = "Menu"; } <h4>現在のアクション:@ViewContext.RouteData.Values["action"]</h4> TempData キー「Food」の値:<strong>@ViewBag.Food</strong> <ul> <li>@Html.ActionLink("1.Menu - メニューを表示するだけ", "Menu")</li> <li>@Html.ActionLink("2.InputTempData : TempData に値をセット", "InputTempData")</li> <li>@Html.ActionLink("3.GetTempData : TempData の値を TempData[\"key\"] で取得し表示します", "GetTempData")</li> <li>@Html.ActionLink("4.PeekTempData : TempData の値を Peek(\"key\") で取得し表示します", "PeekTempData")</li> <li>@Html.ActionLink("5.GetAndKeepTempData : TempData の値を TempData[\"key\"] で取得し、Keep() を実行、表示します", "GetAndKeepTempData")</li> </ul>
確認1
TempData["key"] で取得しない限り、値はずっと保持されます。
- 「2.InputTempData : TempData に値をセット", "InputTempData」をクリック
- 「1.Menu - メニューを表示するだけ」を数回クリック
- 「3.GetTempData : TempData の値を TempData["key"] で取得し表示します」をクリック
- → TempData を取得できる
確認2
Peek("key") で値を取得しても、値はずっと保持されたままです。
- 「2.InputTempData : TempData に値をセット", "InputTempData」をクリック
- 「4.PeekTempData : TempData の値を Peek("key") で取得し表示します」を何回かクリック
- → 全て TempData を取得できる
確認3
TempData["key"] で値を取得しても、Keep() を実行すれば、値は保持されたままです。
- 「2.InputTempData : TempData に値をセット", "InputTempData」をクリック
- 「5.GetAndKeepTempData : TempData の値を TempData["key"] で取得し、Keep() を実行、表示します」をクリック
- → TempData を取得できる
- 「3.GetTempData : TempData の値を TempData["key"] で取得し表示します」をクリック
- → TempData を取得できる
おしまい
あまり使いどころはなさそうですが、TempData が Session をどのように扱っているか分かる例だと思います。
TempData のソースはこちら: TempDataDictionary.cs