ASP中的ViewBag是如何实现的?NET MVC在幕后工作

本文关键字:NET MVC 工作 实现 ViewBag 中的 何实现 ASP | 更新日期: 2023-09-27 18:17:19

我正在看一本关于ASP的书。我想知道下面的例子是如何工作的:

示例# 1

控制器

public class MyController : Controller
{
    public ActionResult Index()
    {
        ViewBag.MyProperty = 5;
        return View();
    }
}
<<h3>视图/h3>
<h1>@ViewBag.MyProperty</h1>

现在我明白了ViewBag是一个动态对象,所以这就是你如何设置属性(虽然我不太了解动态对象,从来没有使用过它们)。但是视图如何从控制器获得ViewBag的特定实例,即使我们没有直接传递任何东西?

我认为ViewBag可以是public static对象,但是对它的任何更改都将是全局的,它不会特定于视图实例。

你能详细说明这在幕后是如何工作的吗?

例2

控制器

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是无状态的。是这样吗?

ASP中的ViewBag是如何实现的?NET MVC在幕后工作

ViewBagControllerBase的一个属性,所有控制器都必须继承它。这是一个dynamic对象,这就是为什么你可以添加新的属性,而不会得到编译时错误。

它不是static,它是对象的成员。在请求生命周期中,控制器实例被创建和处置,因此您不会遇到"并发"问题,例如覆盖值。

View(及其变体)方法也不是static,这就是视图接收ViewBag值的方式:在渲染视图的过程中,控制器实例也有它的ViewBag实例。

如果你分析ControllerBase类,你会看到ViewBag属性是ViewData属性的"代理",只是为了让你的源代码看起来更好。(我甚至记得Scott Hanselman接受Phil Haack的采访,Phil在采访中介绍了ViewBag属性作为ViewData的快捷方式,并消除了重复方括号和引号的需要)。即使ViewBag属性被暴露为dynamic对象,它实现了一个DynamicViewDataDictionary类,直接与ViewData一起工作。

查看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开始

ViewBagControllerBase的属性。定义如下:

public Object ViewBag { get; }

注意这个签名实际上是不正确的。下面是源代码的实际样子:

public dynamic ViewBag {
        get {
            if (_dynamicViewDataDictionary == null) {
                _dynamicViewDataDictionary = new DynamicViewDataDictionary(() => ViewData);
            }
            return _dynamicViewDataDictionary;
        }
    }

_dynamicViewDataDictionary是一个ExpandoObject;您可以在运行时向其添加属性。它的生存期与控制器的生存期相同,即HTTP请求的生存期