[英]How does ViewBag in ASP.NET MVC work behind the scenes?
我正在阅读一本关于ASP.NET MVC的书,我想知道以下示例是如何工作的:
public class MyController : Controller
{
public ActionResult Index()
{
ViewBag.MyProperty = 5;
return View();
}
}
<h1>@ViewBag.MyProperty</h1>
现在我明白ViewBag
是一个动态对象,所以你可以设置属性(虽然我对动态对象ViewBag
,但从未使用它们。)但是视图如何从中获取ViewBag
的特定实例。控制器,即使我们没有直接传递任何东西?
我认为ViewBag
可能是一个public
static
对象,但是对它的任何更改都是全局的,并且它不会特定于视图实例。
你能详细说明这是如何在幕后工作的吗?
public class MyController : Controller
{
public ActionResult Index()
{
ViewBag.MyProperty = 5;
return View();
}
public ActionResult Index2()
{
ViewBag.MyProperty = 6;
return View();
}
}
现在假设首先调用Index
方法,然后调用Index2
。 最后, ViewBag.MyProperty
的值最终为6( Index2
的值)。 我觉得这不是一件好事,但与此同时我觉得我在思考桌面开发术语。 也许与ASP.NET MVC一起使用无关紧要,因为Web是无状态的。 是这样的吗?
ViewBag
是ControllerBase
一个属性,所有控制器都必须继承该属性。 它是一个dynamic
对象,这就是为什么你可以添加新属性而不会出现编译时错误的原因。
它不是static
,它是对象的成员。 在请求生存期间,将创建并处理控制器实例,因此您不会遇到“并发”问题,例如覆盖该值。
View
(及其变体)方法也不是static
,这就是视图接收ViewBag
值的方式:在渲染视图的过程中,控制器实例也有ViewBag实例。
如果您要分析ControllerBase类,您会看到ViewBag属性是ViewData属性的“代理”,只是为了使您的源看起来更好。 (我甚至还记得Scott Hanselman接受Phil Haack的采访,其中Phil引入了ViewBag属性作为ViewData的快捷方式,并且不需要重复的方括号和引号)。 即使将ViewBag
属性公开为dynamic
对象,它ViewBag
实现一个直接与ViewData一起工作的DynamicViewDataDictionary类。
查看Controller类的源代码,您可以找到以下方法:
protected internal virtual ViewResult View(string viewName, string masterName, object model)
所以基本上当你调用return View();
从你的控制器创建一个ActionResult
类的新实例,将ViewData从控制器传递给它的构造函数。 然后将ActionResult
实例传递给特定的视图引擎(ASPX,Razor),以便它可以用于呈现有问题的视图。
使ViewBag / ViewData公共静态可能是有害的。 对MVC应用程序的每个Web请求都会创建一个新的控制器实例。 如果您将ViewData / ViewBag作为公共静态,则两个并发用户将共享ViewBag / ViewData中的相同数据。
这是一个视频。 关于ViewBag(formder ViewModel)的讨论从04:05开始
ViewBag
是ControllerBase
一个属性。 它的定义如下:
public Object ViewBag { get; }
请注意,此签名实际上是不正确的。 以下是源代码的实际内容:
public dynamic ViewBag {
get {
if (_dynamicViewDataDictionary == null) {
_dynamicViewDataDictionary = new DynamicViewDataDictionary(() => ViewData);
}
return _dynamicViewDataDictionary;
}
}
_dynamicViewDataDictionary
是一个ExpandoObject; 您可以在运行时向其添加属性。 它的生命周期与控制器的生命周期相同,后者是HTTP请求的生命周期。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.