在我的ASP.NET MVC4中,我允许控制器通过设置ViewBag.PageTitle来设置当前页面标题。 但
第1部分。当在ChildAction中设置ViewBag.PageTitle时,它不起作用(_Layout.cshtml看不到它);如何从ChildAction设置页面标题?
第2部分。如何在缓存的ChildAction中设置页面标题,因为缓存时不再调用该操作?
谢谢!
public ActionResult Product(long productId)
{
ViewBag.PageTitle="test"; //Works
return View(productId);
}
[OutputCache(Duration=300)]
[ChildActionOnly]
public ActionResult ProductPartial(long productId)
{
Product product=AProductProvider.Instance.GetProduct(productId);
ViewBag.PageTitle=product.Name; //Doesn't work
return View(product);
}
答案 0 :(得分:5)
您可以使用ControllerContext.ParentActionViewContext
检索有关父视图的信息:
[OutputCache(Duration = 300)]
[ChildActionOnly]
public ActionResult ProductPartial(long productId)
{
Product product = AProductProvider.Instance.GetProduct(productId);
ControllerContext.ParentActionViewContext.ViewBag.PageTitle = product.Name;
return View(product);
}
更新:要使其正常工作,您必须在父视图中调用ViewData,如下所示:
@ViewContext.ViewData["PageTitle"]
原因有点模糊。子操作接收对父操作的ViewData(对象的相同实例)的正确引用,但每个视图(ViewPage)都会在状态中接收ViewData的 copy 原始ViewData在Sytem.Web.Mvc.Html.TemplateHelpers.TemplateHelper
方法的视图初始化期间有。在调用子操作发生之前,将初始化/复制父页面的ViewData,因此以后的子操作更新不适用。这是MVC的源代码:
// ....
ViewDataDictionary viewData = new ViewDataDictionary(html.ViewDataContainer.ViewData)
{
Model = metadata.Model,
ModelMetadata = metadata,
TemplateInfo = new TemplateInfo
{
FormattedModelValue = formattedModelValue,
HtmlFieldPrefix = html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(htmlFieldName),
VisitedObjects = new HashSet<object>(html.ViewContext.ViewData.TemplateInfo.VisitedObjects), // DDB #224750
}
};
但是,ViewContext
会保留引用,而不是复制到Controller上下文数据,因此您可以使用该引用。另一方面,如果你使用ViewContext.ViewData
,你必须知道视图,子动作,部分,布局的执行顺序......