c# - net - viewbag razor
¿Cómo funciona ViewBag en ASP.NET MVC detrás de escena? (3)
Estoy leyendo un libro sobre ASP.NET MVC y me pregunto cómo funciona el siguiente ejemplo:
Ejemplo 1
Controlador
public class MyController : Controller
{
public ActionResult Index()
{
ViewBag.MyProperty = 5;
return View();
}
}
Ver
<h1>@ViewBag.MyProperty</h1>
Ahora entiendo que ViewBag
es un objeto dinámico, así es como puedes establecer la propiedad (aunque no sé mucho sobre objetos dinámicos, nunca trabajé con ellos). Pero ¿cómo obtiene la vista la instancia específica del ViewBag
del controlador, a pesar de que no pasamos nada directamente?
Pensé que la ViewBag
podría ser un objeto public
static
, pero cualquier cambio sería global y no sería específico de una instancia de vista.
¿Podría explicarnos cómo funciona esto detrás de escena?
Ejemplo n. ° 2
Controlador
public class MyController : Controller
{
public ActionResult Index()
{
ViewBag.MyProperty = 5;
return View();
}
public ActionResult Index2()
{
ViewBag.MyProperty = 6;
return View();
}
}
Ahora digamos que el método Index
se llama primero, y luego el Index2
. Al final, el valor de ViewBag.MyProperty
terminará como 6 (el valor de Index2
). Siento que no es algo bueno que hacer, pero al mismo tiempo siento que estoy pensando en términos de desarrollo de escritorio. Tal vez no importe cuando se usa con ASP.NET MVC, ya que la web no tiene estado. ¿Es este el caso?
Si analizas la clase ControllerBase verías que la propiedad ViewBag es un "proxy" para la propiedad ViewData solo para que tu fuente se vea mejor. (Incluso recuerdo que Scott Hanselman recibió una entrevista de Phil Haack en la que Phil presentó la propiedad ViewBag como acceso directo a ViewData y eliminó la necesidad de repetir corchetes y comillas). Aunque la propiedad ViewBag
está expuesta como objeto dynamic
, implementa una clase DynamicViewDataDictionary que funciona directamente con ViewData.
En cuanto al código fuente de la clase Controller , puede encontrar este método:
protected internal virtual ViewResult View(string viewName, string masterName, object model)
Así que, básicamente, cuando llamas a return View();
desde su controlador crea una nueva instancia de la clase ActionResult
pasando ViewData del controlador a su constructor. La instancia de ActionResult
se pasa luego a un motor de vista particular (ASPX, Razor) para que se pueda usar para representar una vista en cuestión.
Hacer ViewBag / ViewData public static puede ser dañino. Cada solicitud web a su aplicación MVC crea una nueva instancia de controlador. Si tuviera ViewData / ViewBag como público estático, entonces dos usuarios concurrentes compartirían los mismos datos de ViewBag / ViewData.
Here hay un video. La discusión sobre ViewBag (formder ViewModel) comienza a las 04:05
ViewBag
es una propiedad de ControllerBase
. Se define de la siguiente manera:
public Object ViewBag { get; }
Tenga en cuenta que esta firma es realmente incorrecta. Así es como se ve realmente el código fuente:
public dynamic ViewBag {
get {
if (_dynamicViewDataDictionary == null) {
_dynamicViewDataDictionary = new DynamicViewDataDictionary(() => ViewData);
}
return _dynamicViewDataDictionary;
}
}
_dynamicViewDataDictionary
es un ExpandoObject; puede agregarle propiedades en tiempo de ejecución. Su duración es la misma que la del controlador, que es la duración de la solicitud HTTP.
ViewBag
es una propiedad de ControllerBase
, del que todos los controladores deben heredar. Es un objeto dynamic
, por eso puede agregar nuevas propiedades sin obtener errores de tiempo de compilación.
No es static
, es un miembro del objeto. Durante la vida útil de la solicitud, la instancia del controlador se crea y elimina, por lo que no tendrá problemas de "concurrencia", como sobrescribir el valor.
El método View
(y sus variantes) tampoco es static
, y así es como la vista recibe los valores de ViewBag
: durante el proceso de representación de la vista, la instancia del controlador también tiene su instancia ViewBag.