miso_soup3 Blog

主に ASP.NET 関連について書いています。

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 の値を取得できたとき、ビューに表示します。

f:id:miso_soup3:20131214054725p:plain

TempData はリダイレクトの際によく使われますが、今回は単純に GET リクエストの連続で試してみます。

プロジェクトの用意

Visual Studio のサイト から、Visual Studio Express 2013 for Web(以下、VS Express 2013)をインストールします。

VS Express 2013 を開き、メニューから ファイル>新規作成>プロジェクト を選択します。
「ASP.NET Web アプリケーション」を選択し、OK します。

「MVC」を選択し 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