Question
In ASP.NET MVC (and specifically with Razor), how does one set the value of a variable within a partial (or "sub-template") and access that value within a master (or layout) template?
Goal
I would like to maintain lists of assets (stylesheets and JavaScript files) and be able to add to the lists from within partials. The assets should then be accessible within the master layout to be included in the <head/>
(stylesheets) or near the end of the <body/>
(JavaScript files) of the page. This provides an elegant means of storing modules in partials that include all necessary assets.
My Attempt
Below is what I have tried for stylesheets. The intended result is that both global.css
and view_post.css
would be included in the header, but only global.css
is showing up. It is my understanding that this occurs because the layout is rendered before the template.
Helpers/AssetHelper.cs
namespace MyApp.Helpers
{
public static class AssetHelper
{
private static SortedSet<string> StyleSheets(this HtmlHelper helper)
{
if (helper.ViewBag._styleSheets == null)
helper.ViewBag._styleSheets = new SortedSet<string> ();
return helper.ViewBag._stylesheets as SortedSet<string>;
}
public static MvcHtmlString AddStyleSheet(this HtmlHelper helper, string styleSheet) {
helper.StyleSheets().Add(styleSheet);
return new MvcHtmlString("");
}
public static MvcHtmlString RenderStyles(this HtmlHelper helper)
{
StringBuilder output = new StringBuilder();
string template = "<link rel=\"stylesheet\" type=\"text/css\" href=\"{0}\" />";
foreach (string styleSheet in helper.StyleSheets())
output.Append(String.Format(template, styleSheet));
return new MvcHtmlString(output.ToString());
}
}
}
Views/Shared/Layout.cshtml
@using MyApp.Helpers
<html>
<head>
...
@Html.AddStyleSheet("global.css")
@Html.RenderStyles()
</head>
<body>
...
@RenderBody
...
</body>
</html>
Views/Posts/View.cshtml
@using MyApp.Helpers
@Html.AddStyleSheet("view_post.css")
<h2>...</h2>
<p>...</p>