在ASP.NET MVC中通过子操作设置页面标题

Vin*_*ent 2 c# asp.net asp.net-mvc-4

在我的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);
}
Run Code Online (Sandbox Code Playgroud)

Nen*_*nad 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);
}
Run Code Online (Sandbox Code Playgroud)

更新:要使其工作,在父视图中,您必须调用ViewData,如:

@ViewContext.ViewData["PageTitle"]
Run Code Online (Sandbox Code Playgroud)

理由有点模糊.子操作接收对父操作的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
    }
};
Run Code Online (Sandbox Code Playgroud)

但是,ViewContext保留引用,而不是复制到Controller上下文数据,因此您可以使用该上下文数据.另一方面,如果您使用ViewContext.ViewData,您必须了解视图,子操作,部分,布局的执行顺序......