примечание: <!-- [..] -->
представляет исключенный код для ясности
С _Layout
следующим образом
<!-- [..] -->
@Html.EmitRequiredStylesheet()
</head>
<body>
@await Html.PartialAsync("_Header");
<div class="container body-content">
@RenderBody()
</div>
@await Html.PartialAsync("_Footer");
<!-- [..] -->
партиал _Footer
, содержащий следующий код
<!-- [..] -->
@Html.RequireStylesheet("/css/Footer.css")
<!-- [..] -->
И RequireStylesheet()
а также EmitRequiredStylesheet()
это два метода расширения, которые я адаптировал к .Net Core 2.0 из этот пост следующим образом.
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());
}
Что я пытаюсь здесь сделать, так это иметь частичное представление, способное сообщить _Layout
, какие таблицы стилей/скрипты ему нужны. Как объясняет этот ответ, порядок синтаксического анализа Razor означает, что макет будет анализироваться последним. Но из ответа я ожидал, что мое частичное представление _Footer
будет проанализировано и выполнено до самого _Layout
, а это не так. Отладка с использованием точек останова показала, что вызов @Html.EmitRequiredStylesheet()
выполняется до вызова @Html.RequireStylesheet("/css/Footer.css")
, что означает, что таблица стилей еще не зарегистрирована, когда вызывается первый.
Этот код отлично работал бы, если бы партиал _Footer
вызывался из кода, отображаемого @RenderBody()
, но это не так (это часть макета).
Есть ли какой-нибудь обходной путь, например способ сообщить Razor, что данный партиал должен быть выполнен до самого макета?
Примечание: даже если было бы целесообразно включить таблицу стилей непосредственно в _Layout
, я бы хотел, чтобы она была как можно ближе к коду, с которым она связана. Я действительно не большой поклонник массивных централизованных конфигурационных файлов, и я предпочитаю, чтобы мой include/config выполнялся как можно ближе к коду.
RenderBody()
выполняется сверху вниз, частичные просмотры в порядке их появления 2._Layout
выполняется сверху вниз, вставляя результатыRenderBody()
туда, где он должен. E: - Чтобы сделать то, что вы хотите, вам, вероятно, придется создать некоторые пользовательские функции отложенного рендеринга, а в конце страницы макета сделатьExecuteDelayedRenders()
- person Neil   schedule 01.11.2017