asp.net mvc 3-在局部视图中修改MVC 3 ViewBag不会保留到_Layout.cshtml

我在Razor视图引擎中使用了MVC 3。 我想在局部视图的ViewBag中设置一些值,并想在_Layout.cshtml中检索这些值。 例如,当您设置默认的ASP.NET MVC 3项目时,会在“ / Views / Shared”文件夹中获得_Layout.cshtml文件。 在_Layout.cshtml中,页面标题设置如下:

<title>@ViewBag.PageTitle</title>

然后在“ /Views/Home/About.cshtml”视图中,修改ViewBag的内容:

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

这很好。 呈现“关于”视图时,页面标题为“关于我们”。 因此,现在我想在About视图中渲染一个Partial视图,并在Partial视图中修改ViewBag.Title。 (“ /Views/Shared/SomePartial.cshtml”)

@Html.Partial("SomePartial")

在此部分视图中,我有以下代码:

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

当我调试此代码时,我看到ViewBag.Title设置为“关于我们”,然后在部分视图中看到它被重置为“关于我们从部分视图”,但是当代码到达_Layout.cshtml时,它将 回到“关于我们”。

这是否意味着如果在部分视图中修改了ViewBag的内容,这些更改将不会出现(可访问)在主视图(About.cshtml)或_Layout.cshtml中?

提前致谢!

Zoran asked 2020-08-01T14:59:35Z
10个解决方案
31 votes

如果将ViewBag传递到局部的viewdatadictionary中,然后将其拉出(并强制转换),则可以执行所需的任何操作,并保留引用。 最酷的部分是,由于它是动态的,因此您甚至可以添加属性,然后它们将显示在父页面的Viewbag中。

页:

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

部分:

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

@ViewBag.TheTitle = "New value"
Tony Basallo answered 2020-08-01T15:01:46Z
12 votes

我也遇到了这个问题,找不到任何整洁而明显的解决方案。

我想到的解决方案是实现一个Html扩展方法,该方法返回您定义的'PageData'类,其中包含所需的任何数据:

    [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;
        }
    }

它找到当前请求的顶级控制器,并在同一HTTP请求中每次调用该方法时都返回相同的PageData对象。 第一次在新的HTTP请求中调用它时,它将创建一个新的PageData对象。

Chris answered 2020-08-01T15:01:12Z
8 votes

部分视图拥有自己的ViewBag

您可以从((WebViewPage) WebPageContext.Current.Page).ViewBag获取页面的ViewBag

SLaks answered 2020-08-01T15:02:10Z
7 votes

您可以在部分视图中完成此技巧,以覆盖_Layout.cshtml中的标题:

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

......

<script type="text/javascript">
    document.title = "@ViewBag.Title";
</script>
marianotigre answered 2020-08-01T15:02:30Z
4 votes

正如其他人指出的,“布局”,“视图”和“部分视图”都有自己的ViewBag。 但是,我能够使其与以下产品一起使用:在视图或局部视图中。

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

然后在_Layout中

@ Html.ViewContext.ViewBag.Title

通过显式使用ViewContext,视图可以“重用”相同的ViewBag。

Dax70 answered 2020-08-01T15:03:03Z
1 votes

我尝试了以下方法,它可以工作:

在(父)视图中...

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

注意:将model作为model参数传递,但是必须为viewData参数指定null,才能使用正确的重载。 您不能使用ViewBag,因为Html.Partial不喜欢动态。

然后,在局部视图中...

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

当然,如果您需要将model参数用于真实模型,则必须更具创造力。

Oundless answered 2020-08-01T15:03:41Z
1 votes

尝试使用@SLaks代码

(((WebViewPage) WebPageContext.Current.Page).ViewBag).PropertyName
killebytes answered 2020-08-01T15:04:01Z
0 votes

如果有人仍在寻找解决方案,看来可以使用TempData来解决:

TempData["x"] = x;

TempData一直保留到读取为止,因此您可以在_Layout中读取它。 您只需要注意阅读所有内容,以便在下一个请求时将其清除。

chris answered 2020-08-01T15:04:26Z
-1 votes

使用mvc3时遇到相同的问题,发现

this.ViewBag.ViewBag.PropertyName 

在您的自定义控件中工作。

herui answered 2020-08-01T15:04:50Z
-1 votes

我这是页面数据设计的目的。 将其弹出您的视图。

@Page.somePropertyName = "Whatever you want";

然后在布局视图中访问它。 请务必先检查其是否不为null。

@{
    if(Page.somePropertyName != null)
    {
       //Do stuff
    }
}
Matt answered 2020-08-01T15:05:14Z
translate from https://stackoverflow.com:/questions/4974027/modifying-mvc-3-viewbag-in-a-partial-view-does-not-persist-to-the-layout-cshtml