ASP.NET MVC/Coreで、「ページタイトルをLayoutに渡したい」「一時的にメッセージを表示したい」などの場面で、ViewBag
やViewData
を使ったことはありませんか?これらはどちらも「軽量なデータ渡し手段」として便利ですが、仕組みや用途を正しく理解していないと、保守性の低下やバグの原因になってしまうことも。
本記事では、両者の基本構造から違い、典型的な使い分け例、現場でありがちな落とし穴までを整理します。「型安全なViewModelが第一、補助的にViewBag/ViewData」という原則をベースに、適材適所の判断ができるようになりましょう。
ViewBagとViewDataの基本的な違い
ここでは、ViewBagとViewDataがどのような性質を持っていて、何が異なるのかを比較形式で整理します。
ViewBagは dynamic、ViewDataは 辞書型
特性 | ViewBag | ViewData |
---|---|---|
型 | dynamic |
IDictionary<string, object> |
補完 | 一部効く | 効かない |
型チェック | 実行時 | 実行時(キャスト要) |
✅ ViewBag の特徴
dynamic
を使った糖衣構文(ViewBag.Message = "Hello"
)- 内部的には
ViewData["Message"]
をラップしている - 型安全性がないため、タイポによる実行時エラーのリスクがある
⚠️ 失敗例(タイポ)
ViewBag.Mesage = "こんにちは"; // Message のつもりが誤字
<h2>@ViewBag.Message</h2> // nullが表示されるがエラーにならない
✅ ViewData の特徴
object
型の辞書構造(キャストが必要)- 動的なキー操作が得意(ループ処理など)
- 補完が効かず、ミスを防ぐ仕組みが弱い
⚠️ 冗長な記述
<p>年齢: @(int)ViewData["Age"]</p>
仕組みの違いと技術的背景
このセクションでは、内部的にどう動作しているか、ライフサイクルやパフォーマンスなどの観点から違いを見ていきます。
共通点:同じライフサイクル
- 両者とも HTTPリクエスト単位で生成される
- セッションのようにリクエスト間で値を持ち越すことはできない
👉 どのくらい値が保持されるのか?
- ViewBag / ViewData の値は、1回のHTTPリクエスト内のみ有効です。
return View()
のときはビューで使用可能ですが、RedirectToAction()
などのリダイレクトでは失われます。- リクエストをまたいで値を保持したい場合は
TempData
、Session
などを使いましょう。
ViewBagの dynamic 利便性と落とし穴
- 補完機能のあるエディタ(Visual Studioなど)では使いやすい
- ただし、存在しないプロパティを指定しても気づけない
ViewDataの柔軟性
- 辞書ベースのため、繰り返し処理や動的キー構成が可能
ViewData["Error_1"]
,ViewData["Error_2"]
などのパターン処理に強い
パフォーマンス面の違い
ViewBag
はdynamic
によるリフレクションが介在し、わずかなオーバーヘッドあり- 一方で、数件程度のデータであれば体感差はほとんどない
使い分けのベストプラクティス
「ViewBagとViewData、どちらを使うべきか」に迷う場面は多いものです。ここでは判断の目安となる方針と、用途ごとの具体例を示します。
✅ 原則:まずViewModel、それ以外は例外的用途
ViewModelを使うべきケース:
- 明示的にビューへ複数の値を渡す
- 型安全や補完機能が重要
- 中規模以上のビュー
ViewBag/ViewDataを使ってよいケース:
- 一時的な通知、メッセージ表示
- Layoutや部分ビューに軽量な情報を渡す
- 仮実装やプロトタイプ段階での簡易表示
✅ ViewBag の適用例
// Controller
ViewBag.PageTitle = "ダッシュボード";
<!-- Layout.cshtml -->
<title>@ViewBag.PageTitle - MyApp</title>
こんなときに便利:
- Layoutに共通タイトルを渡したい
- ViewModelを拡張せずに暫定で画面表示をしたい
✅ ViewData の適用例(繰り返しや連番キー)
// Controller
ViewData["Error1"] = "名前が未入力です";
ViewData["Error2"] = "パスワードが短すぎます";
@for (int i = 1; i <= 2; i++)
{
<p class="text-danger">@ViewData[$"Error{i}"]</p>
}
こんなときに便利:
- 同じ構造の複数データを処理したい
- ループや条件分岐が必要な場面
ViewModelとの比較
ここでは、型安全性が確保されるViewModelを使った記述との違いを示し、ViewBag/ViewDataとの対比を行います。
// モデルクラス
public class InfoViewModel
{
public string Message { get; set; }
public int Count { get; set; }
}
// Controller
public IActionResult Info()
{
var model = new InfoViewModel
{
Message = "ようこそ!",
Count = 5
};
return View(model);
}
@model InfoViewModel
<h2>@Model.Message</h2>
@for (int i = 0; i < Model.Count; i++)
{
<p>@i 番目</p>
}
ViewModelの強み:
- 静的型付けで安全
- プロパティの誤りをコンパイル時に検出
- チーム開発やリファクタリングに強い
早見表:ViewBag/ViewDataの比較
どちらを使えばよいか迷ったときのために、判断材料となる比較表を用意しました。
比較項目 | ViewBag | ViewData |
---|---|---|
型安全性 | ❌ | ❌ |
補完機能 | ✅(一部) | ❌ |
型キャスト必要 | ❌ | ✅ |
動的キー処理 | ❌ | ✅ |
使用シーン | 軽量な表示、Layout用 | ループ、連番キー |
NG例 | タイポでnullになる | キーの競合で上書きミス |
まとめ:正しく使えば強力なツール
最後に、これまでのポイントを振り返り、実務での選択判断に役立つ指針を整理します。
ViewBag
とViewData
は便利だが、「仮の用途」や「軽量用途」に限定すべき- 複数値や構造的なデータは必ず
ViewModel
を活用 - 設計判断に迷ったら「型安全性と保守性」を最優先に考える
最終的に目指すべきは、“混在しない、意図の明確なコード”です。 ViewBag
もViewData
も、適切に使えば実務で大いに役立つツールです。選択の軸を明確にし、チーム内で統一された運用ルールを持つことが、バグのない生産的な開発につながります。
コメント