I am using MVC 3 with the Razor view engine. I want to set some values in the ViewBag inside a Partial View and want retrieve those values in my _Layout.cshtml. For exampl
I also had this problem, and couldn't find any neat and obvious solution.
The solution I came up with was to implement an Html extension method that returns a 'PageData' class that you define, containing whatever data you need:
[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;
}
}
It finds the top-level controller for the current request, and returns the same PageData object every time the method is called within the same HTTP request. It creates a new PageData object the first time it is called in a new HTTP request.
As others have pointed out Layout, Views and Partials get their own ViewBag. However, I was able to get it to work with the following: In the View or Partial.
@{ Html.ViewContext.ViewBag.Title = "Reusable Global Variable"; }
Then in _Layout
@Html.ViewContext.ViewBag.Title
By explicitly using the ViewContext, the views 're-use' the same ViewBag.
If you pass the ViewBag into the partial's viewdatadictionary, then pull it out (and cast), you can do whatever you want and the reference is kept. The cool part is that since it's dynamic, you can even add properties and then they'll show up on the parent page's Viewbag.
Page:
//set the viewbag into the partial's view data
@{Html.RenderPartial("Elaborate", Model, new ViewDataDictionary { {"vb", ViewBag}});}
Partial:
@{
var vb = ((dynamic)ViewData["vb"]);
vb.TheTitle = "New values";
}
Page
@ViewBag.TheTitle = "New value"
try @SLaks code with
(((WebViewPage) WebPageContext.Current.Page).ViewBag).PropertyName
I this is what page data is designed for. Pop this into your view.
@Page.somePropertyName = "Whatever you want";
And then access it in your layout view. Be sure to check that its not null first.
@{
if(Page.somePropertyName != null)
{
//Do stuff
}
}
The partial view gets its own ViewBag
.
You can get the page's ViewBag from ((WebViewPage) WebPageContext.Current.Page).ViewBag