Подтвердить что ты не робот

Как ViewBag в ASP.NET MVC работает за кулисами?

Я читаю книгу по ASP.NET MVC, и мне интересно, как работает следующий пример:

Пример # 1

контроллер

public class MyController : Controller
{
    public ActionResult Index()
    {
        ViewBag.MyProperty = 5;

        return View();
    }
}

Вид

<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, так как сеть не имеет апатридов. Это тот случай?

4b9b3361

Ответ 1

ViewBag является свойством ControllerBase, от которого должны наследоваться все контроллеры. Это объект dynamic, поэтому вы можете добавлять к нему новые свойства, не получая ошибок времени компиляции.

Это не static, это элемент объекта. Во время существования запроса экземпляр контроллера создается и удаляется, поэтому у вас не будет проблем с "concurrency", например, для перезаписи значения.

Метод View (и его варианты) также не является static, и это то, как представление получает значения ViewBag: во время процесса визуализации экземпляр контроллера имеет свой экземпляр ViewBag как хорошо.

Ответ 2

Если вы проанализировали класс ControllerBase, вы увидите, что свойство ViewBag является "прокси" для свойства ViewData, чтобы сделать ваш исходный вид лучше. (Я даже помню, как Скотт Гензельман взял интервью у Фила Хаака, где Фил представил свойство 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 public static может быть вредным. Каждый веб-запрос в ваше приложение MVC создает новый экземпляр контроллера. Если у вас будет ViewData/ViewBag как public static, то два одновременных пользователя будут делиться одними и теми же данными из ViewBag/ViewData.

Здесь - это видео. Обсуждение в ViewBag (formder ViewModel) начинается в 04:05

Ответ 3

ViewBag является свойством ControllerBase. Он определяется следующим образом:

public Object ViewBag { get; }

Обратите внимание, что эта подпись фактически неверна. Вот как выглядит исходный код:

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

_dynamicViewDataDictionary - это ExpandoObject; вы можете добавлять к нему свойства во время выполнения. Его срок службы такой же, как у контроллера, который является временем жизни HTTP-запроса.