C# ASP.NET MVC 中的 ViewBag 如何在幕后工作?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16949468/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How does ViewBag in ASP.NET MVC work behind the scenes?
提问by hattenn
I am reading a book on ASP.NET MVC and I'm wondering how the following example works:
我正在阅读一本关于 ASP.NET MVC 的书,我想知道以下示例是如何工作的:
Example #1
示例#1
Controller
控制器
public class MyController : Controller
{
public ActionResult Index()
{
ViewBag.MyProperty = 5;
return View();
}
}
View
看法
<h1>@ViewBag.MyProperty</h1>
Now I understand that ViewBagis a dynamic object, so that's how you can set the property (though I don't know much about dynamic objects, never worked with them.) But how does the view get the specific instance of the ViewBagfrom the controller, even though we don't pass anything directly?
现在我明白这ViewBag是一个动态对象,所以这就是你可以设置属性的方式(虽然我对动态对象不太了解,从来没有使用过它们。)但是视图如何ViewBag从控制器获取特定实例,即使我们没有直接传递任何东西?
I thought that the ViewBagcould be a publicstaticobject, but then any change to it would be global and it wouldn't be specific to a view instance.
我认为ViewBag可能是一个publicstatic对象,但是对它的任何更改都将是全局的,并且不会特定于视图实例。
Could you elaborate as to how this works behind the scenes?
你能详细说明这在幕后是如何工作的吗?
Example #2
示例#2
Controller
控制器
public class MyController : Controller
{
public ActionResult Index()
{
ViewBag.MyProperty = 5;
return View();
}
public ActionResult Index2()
{
ViewBag.MyProperty = 6;
return View();
}
}
Now let's say the Indexmethod is called first, and then the Index2. In the end the value of ViewBag.MyPropertywill end up as 6 (the value from Index2). I feel that it is not a good thing to do, but at the same time I feel that I'm thinking in desktop development terms. Maybe it doesn't matter when used with ASP.NET MVC, as the web is stateless. Is this the case?
现在假设Index首先调用该方法,然后调用Index2. 最后, 的值ViewBag.MyProperty将最终为 6(来自 的值Index2)。我觉得这不是一件好事,但同时我觉得我在考虑桌面开发。也许与 ASP.NET MVC 一起使用并不重要,因为 Web 是无状态的。是这种情况吗?
采纳答案by Andre Calil
ViewBagis a property of ControllerBase, which all controllers must inherit from. It's a dynamicobject, that's why you can add new properties to it without getting compile time errors.
ViewBag是 的属性ControllerBase,所有控制器都必须继承该属性。它是一个dynamic对象,这就是为什么您可以向其添加新属性而不会出现编译时错误的原因。
It's not static, it's a member of the object. During the request lifetime, the controller instance is created and disposed, so you won't have "concurrency" problems, like overwriting the value.
它不是static,它是对象的成员。在请求生命周期内,控制器实例被创建和处理,所以你不会有“并发”问题,比如覆盖值。
The View(and its variants) method is not staticas well, and this is how the view receives the ViewBagvalues: during the process of rendering the view, the controller instance has its ViewBag instance as well.
The View(及其变体)方法不是static这样,这就是视图接收ViewBag值的方式:在渲染视图的过程中,控制器实例也有它的 ViewBag 实例。
回答by Ramunas
If you would analyse ControllerBaseclass you would see that ViewBag property is a "proxy" to ViewData property just to make your source look nicer. (I even remember Scott Hanselman taking interview from Phil Haack where Phil introduced ViewBag property as a shortcut to ViewData and eliminating the need of repeated square brackets and quotes). Even though ViewBagproperty is exposed as dynamicobject it implements a DynamicViewDataDictionaryclass which works directly with ViewData.
如果您分析ControllerBase类,您会看到 ViewBag 属性是 ViewData 属性的“代理”,只是为了让您的源看起来更好。(我什至记得 Scott Hanselman 接受 Phil Haack 的采访,Phil 介绍了 ViewBag 属性作为 ViewData 的快捷方式并消除了重复方括号和引号的需要)。即使ViewBag属性作为dynamic对象公开,它也实现了一个直接与 ViewData 一起工作的DynamicViewDataDictionary类。
Looking at source code of Controllerclass you can find this method:
查看Controller类的源代码,您可以找到此方法:
protected internal virtual ViewResult View(string viewName, string masterName, object model)
So basically when you call return View();from your controller it creates a new instance of ActionResultclass passing ViewData from controller to it's constructor. Instance of ActionResultis then passed to a particular view engine (ASPX, Razor) so it could be used to render a view in question.
所以基本上当你return View();从控制器调用时,它会创建一个新的ActionResult类实例,将 ViewData 从控制器传递给它的构造函数。ActionResult然后将 的实例传递给特定的视图引擎(ASPX、Razor),以便它可以用于呈现有问题的视图。
Making ViewBag/ViewData public static could be harmful. Each web request to your MVC application creates a new instance of controller. If you'd have ViewData/ViewBag as public static then two concurrent users would share same data from ViewBag/ViewData.
将 ViewBag/ViewData 设为公共静态可能是有害的。对 MVC 应用程序的每个 Web 请求都会创建一个新的控制器实例。如果您将 ViewData/ViewBag 作为公共静态,那么两个并发用户将共享来自 ViewBag/ViewData 的相同数据。
Hereis a video. Discussion on ViewBag (formder ViewModel) starts at 04:05
这是一个视频。04:05开始讨论ViewBag(原ViewModel)
回答by Robert Harvey
ViewBagis a property of ControllerBase. It is defined as follows:
ViewBag是 的属性ControllerBase。它的定义如下:
public Object ViewBag { get; }
Note that this signature is actually incorrect. Here's what the source code actually looks like:
请注意,此签名实际上是不正确的。下面是源代码的实际样子:
public dynamic ViewBag {
get {
if (_dynamicViewDataDictionary == null) {
_dynamicViewDataDictionary = new DynamicViewDataDictionary(() => ViewData);
}
return _dynamicViewDataDictionary;
}
}
_dynamicViewDataDictionaryis an ExpandoObject; you can add properties to it at runtime. Its lifetime is the same as that of the controller, which is the lifetime of the HTTP request.
_dynamicViewDataDictionary是一个 ExpandoObject;您可以在运行时为其添加属性。它的生命周期与控制器的生命周期相同,即HTTP请求的生命周期。

