应避免使用 ViewBag 有几个原因:
- ViewBag 是弱类型的
- 您没有在视图中获得 Intellisense
- 您的视图是 ViewBag 和视图模型的混合体,您的视图从不同位置获取信息,而不是将所有内容集中到强类型视图模型中
- ViewBag 不适用于强类型帮助器和表达式,因为动态类型不能与扩展方法一起使用(这不是 ASP.NET MVC 的限制,它是 .NET => 你不能在动态类型上调度扩展方法)
- 由于 ViewBag 的这种弱类型特性,您必须将视图转换为意大利面条代码,因为 HTML 帮助程序希望将特定类型作为参数传递
- ...这个列表还在继续(我真的没有时间填写它,但它是一个非常大的列表)
所以现在我们知道 ViewBag 不好并且不应该使用,有不同的方法可以通过使用视图模型来解决这个要求。
一种可能性是使用Html.Action 助手,它允许您通过完整的控制器/模型/视图生命周期在视图中插入 HTML 的某些部分。这样您就可以拥有一个常用的小部件,而不会干扰您的主视图模型。
另一种可能性是拥有一个基本视图模型,该模型将包含一个表示用户详细信息的属性,并将由一个自定义全局操作过滤器填充,该过滤器可以在每次控制器操作完成执行并返回视图结果时执行。动作过滤器可以拦截这个视图结果,读取身份验证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
)。