Modifying MVC 3 ViewBag in a partial view does not persist to the _Layout.cshtml
我正在使用MVC 3和Razor View引擎。我想在一个局部视图内的视图包中设置一些值,并想在我的layout.cshtml中检索这些值。例如,当您设置默认的ASP.NET MVC 3项目时,会在"/views/shared"文件夹中得到一个u layout.cshtml文件。在该布局中,页面标题设置如下:
1 | @ViewBag.PageTitle |
然后在"/views/home/about.cshtml"视图中修改了视图包的内容:
1 2 3 | @{ ViewBag.Title ="About Us"; } |
这个很好用。呈现"关于"视图时,页面标题为"关于我们"。所以,现在我想在我的"关于"视图中呈现一个局部视图,我想在局部视图中修改viewbag.title。("/views/shared/somepartial.cshtml")。
1 | @Html.Partial("SomePartial") |
在这个局部视图中,我有以下代码:
1 2 3 | @{ ViewBag.Title ="About Us From The Partial View"; } |
当我调试这个代码时,我看到viewbag.title被设置为"关于我们",然后在部分视图中,我看到它被重置为"关于部分视图中的我们",但是当代码到达Layout.cshtml时,它又回到"关于我们"。
这是否意味着,如果在局部视图中修改了ViewBag的内容,那么这些更改将不会显示(可访问)在主视图(about.cshtml)或ulayout.cshtml中?
事先谢谢!
如果将viewbag传递到分部的viewDataDictionary中,然后将其拉出(并强制转换),则可以执行所需的操作,并保留引用。最酷的部分是,由于它是动态的,您甚至可以添加属性,然后它们将显示在父页面的视图包中。
Page:
1 2 | //set the viewbag into the partial's view data @{Html.RenderPartial("Elaborate", Model, new ViewDataDictionary { {"vb", ViewBag}});} |
部分:
1 2 3 4 | @{ var vb = ((dynamic)ViewData["vb"]); vb.TheTitle ="New values"; } |
页
1 | @ViewBag.TheTitle ="New value" |
我也遇到了这个问题,找不到任何清晰而明显的解决方案。
我提出的解决方案是实现一个HTML扩展方法,该方法返回您定义的"pagedata"类,其中包含您需要的任何数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | [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对象。
您可以在部分视图中使用此技巧覆盖u layout.cshtml中的标题:
1 2 3 4 5 6 7 8 | @{ ViewBag.Title ="About Us From The Partial View"; } ...... <script type="text/javascript"> document.title ="@ViewBag.Title"; |
局部视图有自己的
您可以从
正如其他人指出的布局,视图和局部视图都有自己的视图包。但是,我能够让它与以下内容一起工作:在视图中或部分视图中。
1 | @{ Html.ViewContext.ViewBag.Title ="Reusable Global Variable"; } |
然后在布局中
@Html.ViewContext.ViewBag.Title
通过显式使用viewContext,视图"重用"同一个viewBag。
我尝试过以下方法,但效果很好:
在(父)视图中…
1 | @Html.Partial("SomePartial", ViewData, null) |
注:
然后,在局部视图中…
1 2 3 4 | @model ViewDataDictionary @{ Model["Title"] ="About us from the partial view"; } |
当然,如果你需要使用
试用@slaks code
1 | (((WebViewPage) WebPageContext.Current.Page).ViewBag).PropertyName |
如果有人仍在寻找解决方案,您似乎可以使用tempdata:
1 | TempData["x"] = x; |
tempdata被持久化,直到它被读取,所以您可以在您的布局中读取它。你只需小心阅读所有内容,以便下一次请求时清除。
这就是页面数据的设计目的。将此弹出到您的视图中。
1 | @Page.somePropertyName ="Whatever you want"; |
然后在布局视图中访问它。一定要先检查它是否不为空。
1 2 3 4 5 6 | @{ if(Page.somePropertyName != null) { //Do stuff } } |
我在使用MVC3时遇到了同样的问题,我发现
1 | this.ViewBag.ViewBag.PropertyName |
在自定义控件中工作。