アーキテクチャをスマートに。

株式会社ネオジニア代表。ITアーキテクトとしてのお仕事や考えていることなどをたまに綴っています。(記事の内容は個人の見解に基づくものであり、所属組織を代表するものではありません)

ASP.NET MVC 4 ことはじめ(4)ViewBag と ViewData

ViewBag ってなんだ?

自動生成されたビューのソースコードで、冒頭に ViewBag.Title ってやつが登場します。
この ViewBag も ViewData と同じくコントローラからビューにデータを受け渡すための入れ物として使用できます。
MVC 3 から登場したようで、Microsoftは従来の ViewData よりも新しい ViewBag の方を使用するように推奨しているようです。
こんな感じです。
Controllers/HomeController.cs

namespace HelloWorld1.Controllers
{
    public class HomeController : Controller
    {
        //
        // GET: /Home/

        public ActionResult Index()
        {
            ViewBag.MyMessage = "Hello World via ViewBag !";
            return View();
        }
    }
}

Views/Home/Index.cshtml

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @ViewBag.MyMessage
</p>

ViewBag なら型安全

で ViewBag と ViewData の違いについてです。
まず Visual Studio で ViewBag にカーソル合わせて F12 を押すと定義にジャンプするので、見てみるとこうなってます。

namespace System.Web.Mvc
{
	// ...省略...

	public dynamic ViewBag { get; }
	public ViewDataDictionary ViewData { get; set; }

	// ...省略...
}

ViewData と同様に ViewBag も親クラスで定義されていて、dynamic になっています。
なので、スクリプト言語のように宣言なしにいきなりプロパティをセットできますよ、というわけですね。
でも dynamic なので結局 Visual Studio の強力な Intellisense が効かないわけで、個人的にはなんだか微妙な感じです。
ViewData に対する優位点としては、プロパティの型が厳密にチェックされる、ということですかね。

要するに、例えばコントローラ側で

	ViewData["price"] = 100;

とやって、ビュー側で

<p>@(ViewData["price"] * 1.05)</p>

とすると型が不一致で実行時エラーになります。キャストするなり、型変換しないといけません。
でもViewBag なら

	ViewBag.Price = 100;

とやって、ビュー側で

<p>@(ViewBag.Price * 1.05)</p>

としても実行時エラーにならず、より素直に書けます。コレクションや独自のクラスで受け渡ししたい場合は記述がラクになると思います。

ただし、キャストをするのにも一応メリットがあるかもしれません。Intellisense が効くようになるからです。せっかくRubyじゃなくてC#でやるんだから、静的型付け言語の強みを生かしたいし、Intellisense 使えないのはちょっと悲しいですよねぇ。
まぁ、Intellisense が欲しい場合は受け渡しパラメータのためのPOCOクラスを作っておいて、そのインスタンスを渡すようにすればいいのかもしれません。この辺は工夫次第ということですかね。。。

なんか上手いやり方があったら教えて下さい。