在局部视图中修改MVC 3 ViewBag不会保留到_Layout.cshtml
我正在使用MVC3和Razor视图引擎。我想在局部视图中的ViewBag中设置一些值,并想在my_Layout.cshtml中检索这些值。例如,当您设置默认ASP.NET MVC 3项目时,会在“/Views/Shared”文件夹中获得一个_Layout.cshtml文件。在该_Layout.cshtml中,页面标题设置如下:在局部视图中修改MVC 3 ViewBag不会保留到_Layout.cshtml,view,asp.net-mvc-3,razor,partial,viewbag,View,Asp.net Mvc 3,Razor,Partial,Viewbag,我正在使用MVC3和Razor视图引擎。我想在局部视图中的ViewBag中设置一些值,并想在my_Layout.cshtml中检索这些值。例如,当您设置默认ASP.NET MVC 3项目时,会在“/Views/Shared”文件夹中获得一个_Layout.cshtml文件。在该_Layout.cshtml中,页面标题设置如下: <title>@ViewBag.PageTitle</title> 这个很好用。呈现“关于”视图时,页面标题为“关于我们”。因此,现在我想在我的
<title>@ViewBag.PageTitle</title>
这个很好用。呈现“关于”视图时,页面标题为“关于我们”。因此,现在我想在我的About视图中呈现一个局部视图,并修改局部视图中的ViewBag.Title。(“/Views/Shared/SomePartial.cshtml”)
在这个局部视图中,我有以下代码:
@{
ViewBag.Title = "About Us From The Partial View";
}
当我调试这段代码时,我看到ViewBag.Title被设置为“关于我们”,然后在部分视图中,我看到它被重置为“从部分视图关于我们”,但当代码点击_Layout.cshtml时,它返回到“关于我们”
这是否意味着如果在局部视图中修改了ViewBag的内容,则这些更改将不会显示(可访问)在主视图(About.cshtml)或_Layout.cshtml中
提前谢谢 局部视图有自己的
ViewBag
您可以从
((WebViewPage)WebPageContext.Current.page)获取页面的ViewBag。ViewBag
我也遇到了这个问题,找不到任何简洁明了的解决方案
我提出的解决方案是实现一个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对象时创建一个新的PageData对象。如果将ViewBag传递到partial的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";
}
部分:
//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"
尝试使用@SLaks代码
(((WebViewPage) WebPageContext.Current.Page).ViewBag).PropertyName
我在使用mvc3时遇到了同样的问题,我发现
this.ViewBag.ViewBag.PropertyName
在自定义控件中工作。正如其他人所指出的那样,视图和局部视图都有自己的视图包。但是,我能够让它与以下各项一起工作: 在视图中或部分视图中
@{ Html.ViewContext.ViewBag.Title = "Reusable Global Variable"; }
然后在布局中
@Html.ViewContext.ViewBag.Title
通过显式使用ViewContext,视图“重用”相同的ViewBag。您可以在局部视图中执行此操作,以覆盖_Layout.cshtml中的标题:
@{
ViewBag.Title = "About Us From The Partial View";
}
......
<script type="text/javascript">
document.title = "@ViewBag.Title";
</script>
@{
ViewBag.Title=“从局部视图了解我们”;
}
......
document.title=“@ViewBag.title”;
我尝试了以下方法,效果良好:
在(父)视图中
注意:ViewData
作为model
参数传递,但是必须为ViewData
参数指定null
,才能使用正确的重载。您不能使用ViewBag
,因为Html.Partial
不喜欢动态
然后,在局部视图中
@model ViewDataDictionary
@{
Model["Title"] = "About us from the partial view";
}
当然,如果您需要对真实模型使用
model
参数,您必须更具创造性。I这就是页面数据的设计目的。把这个放到你的视野里
@Page.somePropertyName = "Whatever you want";
然后在布局视图中访问它。一定要先检查它是否不是null
@{
if(Page.somePropertyName != null)
{
//Do stuff
}
}
如果有人仍在寻找解决方案,您可以使用TempData:
TempData["x"] = x;
TempData会一直保存到被读取,这样您就可以在_布局中读取它。您只需小心阅读所有内容,以便为下一个请求清除这些内容。这不起作用。我尝试使用该代码在部分视图中修改ViewBag,但是当我在_Layout.cshtml中访问ViewBag时,我仍然拥有在“About”视图中设置的值。这不起作用(至少在MVC 4中)。部分视图具有不同的WebPageContext.Current.Page对象(它有一个特定的部分。我有点惊讶ASP.NET MVC没有提供更好的方法来做到这一点。我所能想到的是,我们正在尝试打破MVC模式,但我们都知道在现实世界中会发生这种情况。我在我当前的项目中找到了绕过此要求的方法,所以我没有机会尝试您的解决方案。但感谢您的输入。我会将其标记为已接受的答案,希望它能帮助其他人。-谢谢。我尝试了此方法,但无效。我制作了一个名为
PageData
的简单类(未显示在您的答案中)使用1string
属性。如果您在局部视图中设置了PageData
的此属性,则它在您的_布局中为null
,因为_布局在局部视图中设置属性之前访问该属性。或者,您可以直接将其添加到页面的视图包中。即,在页面“ViewBag.PageBag=ViewBag;”中,然后在局部视图中“ViewBag.PageBag.Title=”新值”"当我需要在局部视图中设置页面标题以显示在布局标题标记中时,这是我发现唯一可以使用的方法。不幸的是@page与ViewData存在相同的问题:在局部视图中对其所做的更改不会一直保留到布局。请参阅:查看此解决方案,以获得每个请求的单例,作为上面列出的解决方案的替代方案,这非常好:不是100%确定,但我猜你不能更改ViewBag变量,因为基于.Net中的MVC模型,分区更像是更小的、可重用的组件,而不是完整的视图。视图可以使用分区来添加(渲染)这些组件本身,但不是相反。视图还可以将ViewModels传递给partials,以向其提供需要渲染的数据。我知道这不是很有建设性,但我的直觉是,如果您尝试
TempData["x"] = x;