What is the best practice of passing data from a c

2019-05-27 09:51发布

问题:

I currently have a MVC site that needs to have dynamic content on the header of every page.

I currently get the required data as normal in the controller and place it in a View Model. In the view, I take the data and stick the template parts in to the Viewbag and finally, on the main layout page, I take the Viewbag data and pass it to the partial which controls the header.

I've read that I shouldn't use Viewbag where possible, and the amount of times I pass the data round just doesn't feel right.

The only way I can think of to improve this is to create a section on the main layout, and then put the partial/data in the section of the view - however, there are ~30 pages and this again doesn't feel like the correct route.

Is there a better way to do this/what are the best practices for taking dynamic data that has to go to the main view?

回答1:

You can do this with Child Actions. You can reuse this action and even include it in the _Layout page.

Here's a child action to display some header info. It is marked ChildActionOnly so it can only be called within another view. It also takes advantage of OutputCache to save a result for 5 minutes.

[ChildActionOnly]
[OutputCache(Duration = 5 * 60)]
public ActionResult Header(string section)
{
    var info = new HeaderInfo
    {
        Section = section,
        Today = DateTime.Now
    };
    return PartialView("_header", info);
}

_header.cshtml

@model HeaderInfo
<div>
    <span>@Model.Section</span>
    <span>@Model.Today.ToLongTimeString()</span>
</div>

Then use this in a view or layout with Html.Action() or .RenderAction().

@Html.Action("Header", "Home", new { section = "Cake" })
// or
@{Html.RenderAction("Header", "Home", new { section = "Pie" });}

You can specify a section inside your layout then conditionally render if present in the view.

_Layout.cshtml

@RenderSection("header", required: false)

main view

@section header {
    @{Html.RenderAction("Header", "Home", new { section = "Cake" })}
}