ViewBag を避けるべき理由はいくつかあります。
- ViewBag は弱く型付けされています
- ビューでインテリセンスが得られない
- あなたのビューはViewBagとビューモデルの混合物であり、あなたのビューは強く型付けされたビューモデルにすべてを一元化するのではなく、さまざまな場所から情報を取得します
- ViewBag は、動的型を拡張メソッドで使用できないため、強く型付けされたヘルパーと式では機能しません (これは ASP.NET MVC の制限ではなく、.NET です => 動的型で拡張メソッドをディスパッチできません)。
- ViewBag の弱い型付けの性質により、HTML ヘルパーは特定の型が引数として渡されることを想定しているため、ビューをキャストしてスパゲッティ コードにする必要があります。
- ... このリストは続きます (実際に記入する時間はありませんが、非常に大きなリストです)
ViewBag は良くなく、使用すべきではないことがわかったので、ビュー モデルを使用してこの要件を解決するさまざまな方法があります。
1 つの可能性は、Html.Action ヘルパーを使用することです。これにより、完全なコントローラー/モデル/ビュー ライフサイクルを経て、HTML の一部をビューに挿入できます。このようにして、メイン ビュー モデルに干渉することなく、一般的に使用されるウィジェットを持つことができます。
もう 1 つの可能性は、ユーザーの詳細を表すプロパティを含み、コントローラー アクションの実行が終了してビューの結果を返すたびに実行できるカスタム グローバル アクション フィルターによって設定される基本ビュー モデルを持つことです。アクション フィルターは、このビューの結果をインターセプトし、認証 Cookie 情報を読み取り、ビュー モデル プロパティを設定する可能性があります。これは、すべてのビュー モデルが共通の基本ビュー モデルから派生していることを前提としています。このユーザー情報を各ページに表示する必要がある場合、これは明らかに理にかなっています。
例えば:
public class UserInfoInjectorAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
var result = filterContext.Result as ViewResultBase;
if (result == null)
{
// the controller action didn't return any view result => no need to continue
return;
}
var model = result.Model as BaseViewModel;
if (model == null)
{
// the controller action didn't pass a model or the model passed to the view
// doesn't derive from the common base view model that will contain
// the user info property => no need to continbue any further
return;
}
model.UserInfo = ... go ahead and read the forms authentication cookie
userData portion and extract the information
you are looking for
}
}
あとは、このアクション フィルターをグローバル アクション フィルターとして登録するだけで、すべてのコントローラー アクションに適用されます。
すべてのビュー モデルがこれから派生する場合BaseViewModel
、ビューに到着すると、このプロパティの取得を行うコードですべてのコントローラー アクションを汚染することなく、UserInfo プロパティに関連情報が入力されることがわかります。それでも、ビューで強いタイピングが発生します => ViewBag はありません (youpeeee)。
もちろん、特定のシナリオによっては、それを達成するための他の方法があるかもしれません (明らかにViewBag
.