note: <!-- [..] -->
represents excluded code for clarity
With a _Layout
as follow
<!-- [..] -->
@Html.EmitRequiredStylesheet()
</head>
<body>
@await Html.PartialAsync("_Header");
<div class="container body-content">
@RenderBody()
</div>
@await Html.PartialAsync("_Footer");
<!-- [..] -->
a _Footer
partial containing the following code
<!-- [..] -->
@Html.RequireStylesheet("/css/Footer.css")
<!-- [..] -->
And RequireStylesheet()
aswell as EmitRequiredStylesheet()
being two extension methods that I adapted to .Net Core 2.0 from this post as follow
public static string RequireStylesheet(this IHtmlHelper html, string path, int priority = 1)
{
var contextItems = html.ViewContext.HttpContext.Items;
var requiredScripts = contextItems["RequiredStylesheets"] as List<ResourceInclude> ?? new List<ResourceInclude>();
if(requiredScripts.All(i => i.Path != path))
requiredScripts.Add(new ResourceInclude() {Path = path, Priority = priority});
return null;
}
public static HtmlString EmitRequiredStylesheet(this IHtmlHelper html)
{
var contextItems = html.ViewContext.HttpContext.Items;
if(!(contextItems["RequiredStylesheets"] is List<ResourceInclude> requiredScripts))
return null;
var sb = new StringBuilder();
foreach(var item in requiredScripts.OrderByDescending(i => i.Priority))
{
sb.Append($"<link ref=\"{item.Path}\" type=\"stylesheet\" />\n");
}
return new HtmlString(sb.ToString());
}
What I'm trying to do here is to have a partial view be capable of telling the _Layout
which stylesheets/scripts it needs. As this answer explains it the Razor parse order means that the layout will be parsed last. But from the answer I expected my _Footer
partial view to be parsed and exectued before the _Layout
itself, which it is not. Debugging using breakpoints revealed that the @Html.EmitRequiredStylesheet()
call is made before the @Html.RequireStylesheet("/css/Footer.css")
call which means that the stylesheet isn't registered yet when the first one is called.
This code would work perfectly if the _Footer
partial was called from the code rendered by the @RenderBody()
but it is not (it's part of the layout).
Is there any workaround such as a way to tell razor that a given partial must executed before the layout itself ?
Note: even tho it would make sense to include the style sheet directly into the _Layout
I'd like to have it be as close as possible to the code it's related to. I'm really not a big fan of massive centralised config files and I prefer having my includes/config be done as close to the code as possible