Je lis un livre sur ASP.NET MVC et je me demande comment fonctionne l'exemple suivant:
public class MyController : Controller
{
public ActionResult Index()
{
ViewBag.MyProperty = 5;
return View();
}
}
<h1>@ViewBag.MyProperty</h1>
Maintenant, je comprends que ViewBag
est un objet dynamique, c'est ainsi que vous pouvez définir la propriété (même si je ne sais pas grand-chose sur les objets dynamiques, je n'ai jamais travaillé avec eux.) Mais comment la vue obtient-elle l'instance spécifique du ViewBag
du contrôleur, même si nous ne transmettons rien directement?
Je pensais que le ViewBag
pourrait être un objet public
static
, mais alors toute modification serait globale et ne serait pas spécifique à une instance de vue.
Pourriez-vous nous expliquer comment cela fonctionne en coulisses?
public class MyController : Controller
{
public ActionResult Index()
{
ViewBag.MyProperty = 5;
return View();
}
public ActionResult Index2()
{
ViewBag.MyProperty = 6;
return View();
}
}
Supposons maintenant que la méthode Index
soit appelée en premier, puis la Index2
. Au final, la valeur de ViewBag.MyProperty
se terminera par 6 (la valeur de Index2
). Je pense que ce n'est pas une bonne chose à faire, mais en même temps, je pense que je pense en termes de développement de bureau. Peut-être que cela n'a pas d'importance lorsqu'il est utilisé avec ASP.NET MVC, car le Web est sans état. Est-ce le cas?
ViewBag
est une propriété de ControllerBase
, dont tous les contrôleurs doivent hériter. C'est un objet dynamic
, c'est pourquoi vous pouvez y ajouter de nouvelles propriétés sans obtenir d'erreurs de compilation.
Ce n'est pas static
, c'est un membre de l'objet. Pendant la durée de vie de la demande, l'instance de contrôleur est créée et supprimée, vous n'aurez donc pas de problèmes de "concurrence", comme l'écrasement de la valeur.
La méthode View
(et ses variantes) n'est pas également static
, et c'est ainsi que la vue reçoit les valeurs ViewBag
: pendant le processus de rendu de la vue, le contrôleur l'instance a également son instance ViewBag.
Si vous analysiez la classe ControllerBase , vous verriez que la propriété ViewBag est un "proxy" de la propriété ViewData juste pour rendre votre source plus belle. (Je me souviens même que Scott Hanselman avait interviewé Phil Haack où Phil a présenté la propriété ViewBag comme raccourci vers ViewData et éliminé le besoin de crochets et de guillemets répétés). Même si la propriété ViewBag
est exposée en tant qu'objet dynamic
, elle implémente une classe DynamicViewDataDictionary qui fonctionne directement avec ViewData.
En regardant le code source de la classe Controller , vous pouvez trouver cette méthode:
protected internal virtual ViewResult View(string viewName, string masterName, object model)
Donc, fondamentalement, lorsque vous appelez return View();
à partir de votre contrôleur, il crée une nouvelle instance de la classe ActionResult
en passant ViewData du contrôleur à son constructeur. L'instance de ActionResult
est ensuite passée à un moteur de vue particulier (ASPX, Razor) afin qu'elle puisse être utilisée pour rendre une vue en question.
Rendre ViewBag/ViewData public statique pourrait être dangereux. Chaque demande Web à votre application MVC crée une nouvelle instance de contrôleur. Si vous aviez ViewData/ViewBag comme statique publique, deux utilisateurs simultanés partageraient les mêmes données de ViewBag/ViewData.
Ici est une vidéo. La discussion sur ViewBag (formder ViewModel) commence à 04:05
ViewBag
est une propriété de ControllerBase
. Il est défini comme suit:
public Object ViewBag { get; }
Notez que cette signature est en fait incorrecte. Voici à quoi ressemble réellement le code source:
public dynamic ViewBag {
get {
if (_dynamicViewDataDictionary == null) {
_dynamicViewDataDictionary = new DynamicViewDataDictionary(() => ViewData);
}
return _dynamicViewDataDictionary;
}
}
_dynamicViewDataDictionary
est un ExpandoObject; vous pouvez lui ajouter des propriétés lors de l'exécution. Sa durée de vie est la même que celle du contrôleur, qui est la durée de vie de la requête HTTP.