Posted at
ASP.NETDay 15

レイアウトファイルとそれを使用した画面ファイル間でのViewBagの挙動

More than 3 years have passed since last update.

ViewBagの値をレイアウトファイルでデフォルトを設定して、各画面で上書きしたい事があったので調べてみました。

結論から書くと、body(各画面) → layoutの順で実行されるので、

『bodyの内容をlayoutで上書きするかどうか』

という視点で見ていくことになります。


上書きできないパターン(正しくは_Layout.cshtml『で』上書きしているパターン)


Detail.cshtml

@{ ViewBag.isHoge = true; }



_Layout.cshtml

@{ ViewBag.isHoge = false; } // "_Layout.cshtmlで上書き"する形になる

@( ViewBag.isHoge ? "hoge" : "fuga" ) // fugaを出力

こちらの書き方ですと、先にDetail.cshtmlでisHogeが定義されてLayout.cshtmlで値が上書されてしまいます。結果としてfugaが出力されてしまいます。


上書きできるパターン(正しくは_Layout.cshtml『で』上書きしていないパターン)


Detail.cshtml

@{ ViewBag.isHoge = true; }



_Layout.cshtml

@{ 

if (ViewBag.isHoge == null) { // Detail.cshtmlで設定されているのでnullではない
ViewBag.isHoge = false; // したがってここは通らない
}
}
@( ViewBag.isHoge ? "hoge" : "fuga" ) // hogeを出力

こちらの書き方は、先にDetail.cshtmlでisHogeが定義されますが、Layout.cshtml内でnullチェックをしているため、定義済みの場合に値が上書されません。結果としてhogeが出力されます。


まとめ

個人的にはレイアウトファイルが先に読まれるだろうと思っていたので、ちょっと意外でした。

Webページのタイトル等、デフォルトはあるけども一部ページでは書き換えたい時などに使えるかなと思います。