La modification de MVC 3 ViewBag dans une vue partielle ne persiste pas dans le fichier _Layout.cshtml

J’utilise MVC 3 avec le moteur de vue Razor. Je souhaite définir certaines valeurs dans ViewBag dans une vue partielle et je souhaite récupérer ces valeurs dans mon fichier _Layout.cshtml. Par exemple, lorsque vous configurez un projet ASP.NET MVC 3 par défaut, vous obtenez un fichier _Layout.cshtml dans le dossier “/ Views / Shared”. Dans ce _Layout.cshtml le titre de la page est défini comme ceci:

@ViewBag.PageTitle 

Ensuite, dans “/Views/Home/About.cshtml”, le contenu de ViewBag est modifié:

 @{ ViewBag.Title = "About Us"; } 

Cela fonctionne bien. Lorsque la vue À propos est rendue, le titre de la page est “À propos de nous”. Donc, maintenant, je veux rendre une vue partielle à l’intérieur de ma vue A propos et je veux modifier le titre ViewBag.Tit dans ma vue partielle. (“/Views/Shared/SomePartial.cshtml”)

 @Html.Partial("SomePartial") 

Dans cette vue partielle j’ai ce code:

 @{ ViewBag.Title = "About Us From The Partial View"; } 

Lorsque je débogue ce code, je vois que le ViewBag.Title est réglé sur “About Us”, puis dans la vue Partial, je le vois réinitialisé sur “About Us from Partial View”, mais lorsque le code frappe le fichier _Layout.cshtml, il disparaît. retour à “About Us”.

Cela signifie-t-il que si le contenu de ViewBag est modifié dans une vue partielle, ces modifications n’apparaîtront pas (être accessibles) dans la vue principale (About.cshtml) ou dans le fichier _Layout.cshtml?

Merci d’avance!

    J’ai aussi eu ce problème et je n’ai pas trouvé de solution nette et évidente.

    La solution que j’ai trouvée consistait à implémenter une méthode d’extension Html qui retourne une classe ‘PageData’ que vous définissez, contenant toutes les données dont vous avez besoin:

      [ThreadStatic] private static ControllerBase pageDataController; [ThreadStatic] private static PageData pageData; public static PageData GetPageData(this HtmlHelper html) { ControllerBase controller = html.ViewContext.Controller; while (controller.ControllerContext.IsChildAction) { controller = controller.ControllerContext.ParentActionViewContext.Controller; } if (pageDataController == controller) { return pageData; } else { pageDataController = controller; pageData = new PageData(); return pageData; } } 

    Il trouve le contrôleur de niveau supérieur pour la requête en cours et renvoie le même object PageData à chaque appel de la méthode dans la même requête HTTP. Il crée un nouvel object PageData lors de sa première utilisation dans une nouvelle requête HTTP.

    Si vous passez le ViewBag dans le viewdatadictionary du partiel, puis le retirez (et le convertissez), vous pouvez faire ce que vous voulez et la référence est conservée. La partie la plus intéressante est que, étant dynamic, vous pouvez même append des propriétés puis les afficher sur le Viewbag de la page parente.

    Page:

     //set the viewbag into the partial's view data @{Html.RenderPartial("Elaborate", Model, new ViewDataDictionary { {"vb", ViewBag}});} 

    Partiel:

     @{ var vb = ((dynamic)ViewData["vb"]); vb.TheTitle = "New values"; } 

    Page

     @ViewBag.TheTitle = "New value" 

    La vue partielle a son propre ViewBag .

    Vous pouvez obtenir le ViewBag de la page depuis ((WebViewPage) WebPageContext.Current.Page).ViewBag

    Vous pouvez faire cette astuce dans votre vue partielle pour remplacer le titre dans votre fichier _Layout.cshtml:

     @{ ViewBag.Title = "About Us From The Partial View"; } ......  

    Comme d’autres l’ont souligné, Layout , Views et Partials ont leur propre ViewBag . Cependant, j’ai pu le faire fonctionner avec les éléments suivants: Dans la vue ou partielle.

     @{ Html.ViewContext.ViewBag.Title = "Reusable Global Variable"; } 

    Puis dans _Layout

    @ Html.ViewContext.ViewBag.Title

    En utilisant explicitement ViewContext , les vues “ré-utilisent” le même ViewBag.

    J’ai essayé ce qui suit et ça marche:

    Dans la vue (parent) …

     @Html.Partial("SomePartial", ViewData, null) 

    Remarque: ViewData est transmis en tant qu’argument de model , mais vous devez spécifier null pour que l’argument viewData utilise la surcharge correcte. Vous ne pouvez pas utiliser ViewBag car Html.Partial n’aime pas la dynamic.

    Puis, dans la vue partielle …

     @model ViewDataDictionary @{ Model["Title"] = "About us from the partial view"; } 

    Bien sûr, si vous devez utiliser l’argument du model pour un modèle réel, vous devrez être plus créatif.

    essayez le code @SLaks avec

     (((WebViewPage) WebPageContext.Current.Page).ViewBag).PropertyName 

    Si quelqu’un cherche encore une solution, il semble que vous puissiez le faire avec TempData:

     TempData["x"] = x; 

    TempData est conservé jusqu’à ce qu’il soit lu, vous pouvez donc le lire dans votre _Layout. Vous devez juste faire attention à tout lire pour qu’elle soit effacée pour la prochaine demande.

    J’ai rencontré le même problème lorsque j’utilise mvc3, et j’ai trouvé que

     this.ViewBag.ViewBag.PropertyName 

    fonctionne dans votre contrôle personnalisé.

    I c’est à quoi les données de la page sont conçues. Pop ceci dans votre vue.

     @Page.somePropertyName = "Whatever you want"; 

    Et puis accédez-y dans votre vue de mise en page. Assurez-vous de vérifier que sa valeur n’est pas nulle en premier.

     @{ if(Page.somePropertyName != null) { //Do stuff } }