Modifying MVC 3 ViewBag in a partial view does not

2019-01-17 05:59发布

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 example, when you setup a default ASP.NET MVC 3 project you get a _Layout.cshtml file in the "/Views/Shared" folder. In that _Layout.cshtml the Page Title is set like this:

<title>@ViewBag.PageTitle</title>

Then in "/Views/Home/About.cshtml" view the contents of the ViewBag are modified:

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

This works fine. When the About view is rendered the page title is "About Us". So, now I want to render a Partial view inside my About view and I want to modify the ViewBag.Title inside my Partial view. ("/Views/Shared/SomePartial.cshtml")

@Html.Partial("SomePartial")

In this Partial view I have this code:

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

When I debug this code I see the ViewBag.Title get set to "About Us" and then in the Partial view I see it get reset to "About Us From The Partial View", but when the code hits the _Layout.cshtml it goes back to "About Us".

Does this mean that if the contents of the ViewBag are modified in a Partial view, those changes will not appear(be accessible) in the main view (About.cshtml) or the _Layout.cshtml?

Thanks in advance!

10条回答
三岁会撩人
2楼-- · 2019-01-17 06:12

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.

查看更多
一夜七次
3楼-- · 2019-01-17 06:13

try @SLaks code with

(((WebViewPage) WebPageContext.Current.Page).ViewBag).PropertyName
查看更多
姐就是有狂的资本
4楼-- · 2019-01-17 06:13

If anyone is still looking for a solution to this it appears that you can do it with TempData:

TempData["x"] = x;

TempData is persisted until it is read so you can just read it in your _Layout. You just have to be careful that you read everything so that it is cleared for the next request.

查看更多
疯言疯语
5楼-- · 2019-01-17 06:16

You can do this trick in your partial view to override the title in your _Layout.cshtml:

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

......

<script type="text/javascript">
    document.title = "@ViewBag.Title";
</script>
查看更多
Root(大扎)
6楼-- · 2019-01-17 06:17

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"
查看更多
孤傲高冷的网名
7楼-- · 2019-01-17 06:18

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
    }
}
查看更多
登录 后发表回答