3

在我的 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);
}
4

1 回答 1

6

您可以使用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 的状态接收 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保留引用,而不是复制到控制器上下文数据,因此您可以使用那个。另一方面,如果您使用ViewContext.ViewData,则必须了解视图、子操作、部分、布局的执行顺序......

于 2013-10-04T23:40:31.407 回答