Заполните раздел бритвы из частичного
Моя основная мотивация для этого - получить Javascript, который требуется только частичным в нижней части страницы, с остальной частью Javascript, а не в середине страницы, где отображается частичная.
Вот упрощенный пример того, что я пытаюсь сделать:
Вот макет с секцией Scripts прямо перед телом.
<!DOCTYPE html>
<html>
<head>
<title>@ViewBag.Title</title>
<link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
</head>
<body>
@RenderBody()
<script src="@Url.Content("~/Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>
@RenderSection("Scripts", false)
</body>
</html>
Здесь показан пример с использованием этого макета.
<h2>This is the view</h2>
@{Html.RenderPartial("_Partial");}
@section Scripts {
<script type="text/javascript">
alert("I'm a view.");
</script>
}
И здесь частичное отображение из представления.
<p>This is the partial.</p>
@* this never makes it into the rendered page *@
@section Scripts {
<script type="text/javascript">
alert("I'm a partial.");
</script>
}
В этом примере разметка, указанная в представлении, помещается в раздел, но разметка из частичного нет. Можно ли заполнить секцию с частичного представления с помощью Razor? Если нет, то каковы некоторые другие методы получения Javascript, которые нужны только частичным в нижней части страницы, не включая их глобально?
Ответы
Ответ 1
То, как я рассматривал это, - написать пару методов расширения для класса HtmlHelper. Это позволяет частичным представлениям сказать, что им требуется script, а затем в представлении макета, который записывает тег, который я вызываю на мой вспомогательный метод, чтобы испускать необходимые сценарии
Вот вспомогательные методы:
public static string RequireScript(this HtmlHelper html, string path, int priority = 1)
{
var requiredScripts = HttpContext.Current.Items["RequiredScripts"] as List<ResourceInclude>;
if (requiredScripts == null) HttpContext.Current.Items["RequiredScripts"] = requiredScripts = new List<ResourceInclude>();
if (!requiredScripts.Any(i => i.Path == path)) requiredScripts.Add(new ResourceInclude() { Path = path, Priority = priority });
return null;
}
public static HtmlString EmitRequiredScripts(this HtmlHelper html)
{
var requiredScripts = HttpContext.Current.Items["RequiredScripts"] as List<ResourceInclude>;
if (requiredScripts == null) return null;
StringBuilder sb = new StringBuilder();
foreach (var item in requiredScripts.OrderByDescending(i => i.Priority))
{
sb.AppendFormat("<script src=\"{0}\" type=\"text/javascript\"></script>\n", item.Path);
}
return new HtmlString(sb.ToString());
}
public class ResourceInclude
{
public string Path { get; set; }
public int Priority { get; set; }
}
Как только у вас есть это место, ваше частичное представление просто нужно вызвать @Html.RequireScript("/Path/To/Script")
.
И в разделе заголовка макета вы вызываете @Html.EmitRequiredScripts()
.
Дополнительным преимуществом этого является то, что он позволяет отсеять дубликаты запросов script. Если у вас несколько видов/частичных представлений, которым требуется данный script, вы можете с уверенностью предположить, что вы будете выводить его только один раз
Ответ 2
Частичные представления не могут участвовать в разделах их родительских представлений.
Ответ 3
У вас может быть вторая часть, которая отвечает только за инъекцию необходимого javascript. Поместите несколько скриптов вокруг блоков @if
, если хотите:
@model string
@if(Model == "bla") {
<script type="text/javascript">...</script>
}
@else if(Model == "bli") {
<script type="text/javascript">...</script>
}
Это можно было бы немного очистить, но затем в разделе Scripts
вашего представления:
@section Scripts
{
@Html.Partial("_Scripts", "ScriptName_For_Partial1")
}
Опять же, он может не выиграть приз красоты, но он будет работать.
Ответ 4
Более элегантный способ сделать это - перенести частичные сценарии просмотра в отдельный файл, а затем визуализировать его в разделе "Сценарии":
<h2>This is the view</h2>
@Html.RenderPartial("_Partial")
@section Scripts
{
@Html.RenderPartial("_PartialScripts")
<script type="text/javascript">
alert("I'm a view script.");
</script>
}
Частичный вид _Partial.cshtml:
<p>This is the partial.</p>
Частичный вид _PartialScripts.cshtml только с скриптами:
<script type="text/javascript">
alert("I'm a partial script!");
</script>
Ответ 5
Установите пакет Forloop.HtmlHelpers nuget - он добавляет некоторые помощники для управления скриптами в частичных представлениях и шаблонах редакторов.
Где-то в вашем макете вам нужно позвонить
@Html.RenderScripts()
Это будет где любые script файлы и script блоки будут выводиться на странице, поэтому я бы порекомендовал разместить их после ваших основных сценариев в макете и после раздела скриптов (если он у вас есть).
Если вы используете Структуру веб-оптимизации с пакетом, вы можете использовать перегрузку
@Html.RenderScripts(Scripts.Render)
чтобы этот метод использовался для записи файлов script.
Теперь, когда вы хотите добавить script файлы или блоки в виде, частичном представлении или шаблоне, просто используйте
@using (Html.BeginScriptContext())
{
Html.AddScriptFile("~/Scripts/jquery.validate.js");
Html.AddScriptBlock(
@<script type="text/javascript">
$(function() { $('#someField').datepicker(); });
</script>
);
}
Помощники гарантируют, что только одна ссылка на файл script отображается, если добавляется несколько раз, а также гарантирует, что файлы script отображаются в ожидаемом порядке, т.е.
- Layout
- Частицы и шаблоны (в том порядке, в котором они отображаются в представлении сверху вниз)
Ответ 6
[Обновленная версия]
Обновленная версия, следующая за вопросом @Necrocubus для включения встроенных скриптов.
public static class ScriptsExtensions
{
const string REQ_SCRIPT = "RequiredScript";
const string REQ_INLINESCRIPT = "RequiredInlineScript";
const string REQ_STYLE = "RequiredStyle";
#region Scripts
/// <summary>
/// Adds a script
/// </summary>
/// <param name="html"></param>
/// <param name="path"></param>
/// <param name="priority">Ordered by decreasing priority </param>
/// <param name="bottom"></param>
/// <param name="options"></param>
/// <returns></returns>
public static string RequireScript(this IHtmlHelper html, string path, int priority = 1, bool bottom=false, params string[] options)
{
var ctxt = html.ViewContext.HttpContext;
var requiredScripts = ctxt.Items[REQ_SCRIPT] as List<ResourceToInclude>;
if (requiredScripts == null) ctxt.Items[REQ_SCRIPT] = requiredScripts = new List<ResourceToInclude>();
if (!requiredScripts.Any(i => i.Path == path)) requiredScripts.Add(new ResourceToInclude() { Path = path, Priority = priority, Options = options, Type=ResourceType.Script, Bottom=bottom});
return null;
}
/// <summary>
///
/// </summary>
/// <param name="html"></param>
/// <param name="script"></param>
/// <param name="priority">Ordered by decreasing priority </param>
/// <param name="bottom"></param>
/// <returns></returns>
public static string RequireInlineScript(this IHtmlHelper html, string script, int priority = 1, bool bottom = false)
{
var ctxt = html.ViewContext.HttpContext;
var requiredScripts = ctxt.Items[REQ_INLINESCRIPT] as List<InlineResource>;
if (requiredScripts == null) ctxt.Items[REQ_INLINESCRIPT] = requiredScripts = new List<InlineResource>();
requiredScripts.Add(new InlineResource() { Content=script, Priority = priority, Bottom=bottom, Type=ResourceType.Script});
return null;
}
/// <summary>
/// Just call @Html.EmitRequiredScripts(false)
/// at the end of your head tag and
/// @Html.EmitRequiredScripts(true) at the end of the body if some scripts are set to be at the bottom.
/// </summary>
public static HtmlString EmitRequiredScripts(this IHtmlHelper html, bool bottom)
{
var ctxt = html.ViewContext.HttpContext;
var requiredScripts = ctxt.Items[REQ_SCRIPT] as List<ResourceToInclude>;
var requiredInlineScripts = ctxt.Items[REQ_INLINESCRIPT] as List<InlineResource>;
var scripts = new List<Resource>();
scripts.AddRange(requiredScripts ?? new List<ResourceToInclude>());
scripts.AddRange(requiredInlineScripts ?? new List<InlineResource>());
if (scripts.Count==0) return null;
StringBuilder sb = new StringBuilder();
foreach (var item in scripts.Where(s=>s.Bottom==bottom).OrderByDescending(i => i.Priority))
{
sb.Append(item.ToString());
}
return new HtmlString(sb.ToString());
}
#endregion Scripts
#region Styles
/// <summary>
///
/// </summary>
/// <param name="html"></param>
/// <param name="path"></param>
/// <param name="priority">Ordered by decreasing priority </param>
/// <param name="options"></param>
/// <returns></returns>
public static string RequireStyle(this IHtmlHelper html, string path, int priority = 1, params string[] options)
{
var ctxt = html.ViewContext.HttpContext;
var requiredScripts = ctxt.Items[REQ_STYLE] as List<ResourceToInclude>;
if (requiredScripts == null) ctxt.Items[REQ_STYLE] = requiredScripts = new List<ResourceToInclude>();
if (!requiredScripts.Any(i => i.Path == path)) requiredScripts.Add(new ResourceToInclude() { Path = path, Priority = priority, Options = options });
return null;
}
/// <summary>
/// Just call @Html.EmitRequiredStyles()
/// at the end of your head tag
/// </summary>
public static HtmlString EmitRequiredStyles(this IHtmlHelper html)
{
var ctxt = html.ViewContext.HttpContext;
var requiredScripts = ctxt.Items[REQ_STYLE] as List<ResourceToInclude>;
if (requiredScripts == null) return null;
StringBuilder sb = new StringBuilder();
foreach (var item in requiredScripts.OrderByDescending(i => i.Priority))
{
sb.Append(item.ToString());
}
return new HtmlString(sb.ToString());
}
#endregion Styles
#region Models
public class InlineResource : Resource
{
public string Content { get; set; }
public override string ToString()
{
return "<script>"+Content+"</script>";
}
}
public class ResourceToInclude : Resource
{
public string Path { get; set; }
public string[] Options { get; set; }
public override string ToString()
{
switch(Type)
{
case ResourceType.CSS:
if (Options == null || Options.Length == 0)
return String.Format("<link rel=\"stylesheet\" href=\"{0}\" type=\"text/css\" />\n", Path);
else
return String.Format("<link rel=\"stylesheet\" href=\"{0}\" type=\"text/css\" {1} />\n", Path, String.Join(" ", Options));
default:
case ResourceType.Script:
if (Options == null || Options.Length == 0)
return String.Format("<script src=\"{0}\" type=\"text/javascript\"></script>\n", Path);
else
return String.Format("<script src=\"{0}\" type=\"text/javascript\" {1}></script>\n", Path, String.Join(" ", Options));
}
}
}
public class Resource
{
public ResourceType Type { get; set; }
public int Priority { get; set; }
public bool Bottom { get; set; }
}
public enum ResourceType
{
Script,
CSS
}
#endregion Models
}
Мои 2 цента, это старая должность, но по-прежнему актуальная, так что вот обновленное обновление решения г-на Белла, которое работает с ASP.Net Core.
Он позволяет добавлять сценарии и стили к основному макету из импортированных частичных представлений и подзаголовков и возможность добавлять опции для импорта script/style (например, async defer и т.д.):
public static class ScriptsExtensions
{
const string REQ_SCRIPT = "RequiredScript";
const string REQ_STYLE = "RequiredStyle";
public static string RequireScript(this IHtmlHelper html, string path, int priority = 1, params string[] options)
{
var ctxt = html.ViewContext.HttpContext;
var requiredScripts = ctxt.Items[REQ_SCRIPT] as List<ResourceInclude>;
if (requiredScripts == null) ctxt.Items[REQ_SCRIPT] = requiredScripts = new List<ResourceInclude>();
if (!requiredScripts.Any(i => i.Path == path)) requiredScripts.Add(new ResourceInclude() { Path = path, Priority = priority, Options = options });
return null;
}
public static HtmlString EmitRequiredScripts(this IHtmlHelper html)
{
var ctxt = html.ViewContext.HttpContext;
var requiredScripts = ctxt.Items[REQ_SCRIPT] as List<ResourceInclude>;
if (requiredScripts == null) return null;
StringBuilder sb = new StringBuilder();
foreach (var item in requiredScripts.OrderByDescending(i => i.Priority))
{
if (item.Options == null || item.Options.Length == 0)
sb.AppendFormat("<script src=\"{0}\" type=\"text/javascript\"></script>\n", item.Path);
else
sb.AppendFormat("<script src=\"{0}\" type=\"text/javascript\" {1}></script>\n", item.Path, String.Join(" ", item.Options));
}
return new HtmlString(sb.ToString());
}
public static string RequireStyle(this IHtmlHelper html, string path, int priority = 1, params string[] options)
{
var ctxt = html.ViewContext.HttpContext;
var requiredScripts = ctxt.Items[REQ_STYLE] as List<ResourceInclude>;
if (requiredScripts == null) ctxt.Items[REQ_STYLE] = requiredScripts = new List<ResourceInclude>();
if (!requiredScripts.Any(i => i.Path == path)) requiredScripts.Add(new ResourceInclude() { Path = path, Priority = priority, Options = options });
return null;
}
public static HtmlString EmitRequiredStyles(this IHtmlHelper html)
{
var ctxt = html.ViewContext.HttpContext;
var requiredScripts = ctxt.Items[REQ_STYLE] as List<ResourceInclude>;
if (requiredScripts == null) return null;
StringBuilder sb = new StringBuilder();
foreach (var item in requiredScripts.OrderByDescending(i => i.Priority))
{
if (item.Options == null || item.Options.Length == 0)
sb.AppendFormat("<link rel=\"stylesheet\" href=\"{0}\" type=\"text/css\" />\n", item.Path);
else
sb.AppendFormat("<link rel=\"stylesheet\" href=\"{0}\" type=\"text/css\" {1} />\n", item.Path, String.Join(" ", item.Options));
}
return new HtmlString(sb.ToString());
}
public class ResourceInclude
{
public string Path { get; set; }
public int Priority { get; set; }
public string[] Options { get; set; }
}
}
Ответ 7
Основываясь на ответе г-на Белла и Шимми выше, я добавляю дополнительную функцию для Bundle script.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Text;
using System.Web.Mvc;
namespace ABC.Utility
{
public static class PartialViewHelper
{
public static string RequireScript(this HtmlHelper html, string path, int priority = 1)
{
var requiredScripts = HttpContext.Current.Items["RequiredScripts"] as List<ResourceInclude>;
if (requiredScripts == null) HttpContext.Current.Items["RequiredScripts"] = requiredScripts = new List<ResourceInclude>();
if (!requiredScripts.Any(i => i.Path == path)) requiredScripts.Add(new ResourceInclude() { Path = path, Priority = priority });
return null;
}
public static string RequireBundleStyles(this HtmlHelper html, string bundleName)
{
var a = System.Web.Optimization.Styles.Render(bundleName);
var requiredStyles = HttpContext.Current.Items["RequiredStyles"] as IHtmlString;
if (requiredStyles == null) HttpContext.Current.Items["RequiredStyles"] = requiredStyles = a;
return null;
}
public static string RequireBundleScripts(this HtmlHelper html, string bundleName)
{
var a=System.Web.Optimization.Scripts.Render(bundleName);
var requiredScripts = HttpContext.Current.Items["RequiredScripts"] as IHtmlString;
if (requiredScripts == null) HttpContext.Current.Items["RequiredScripts"] = requiredScripts = a;
return null;
}
public static HtmlString EmitRequiredBundleStyles(this HtmlHelper html)
{
var requiredStyles = HttpContext.Current.Items["RequiredStyles"] as IHtmlString;
if (requiredStyles == null) return null;
return MvcHtmlString.Create(requiredStyles.ToHtmlString()) ;
}
public static HtmlString EmitRequiredBundleScripts(this HtmlHelper html)
{
var requiredScripts = HttpContext.Current.Items["RequiredScripts"] as IHtmlString;
if (requiredScripts == null) return null;
return MvcHtmlString.Create(requiredScripts.ToHtmlString());
}
public static HtmlString EmitRequiredScripts(this HtmlHelper html)
{
var requiredScripts = HttpContext.Current.Items["RequiredScripts"] as List<ResourceInclude>;
if (requiredScripts == null) return null;
StringBuilder sb = new StringBuilder();
foreach (var item in requiredScripts.OrderByDescending(i => i.Priority))
{
sb.AppendFormat("<script src=\"{0}\" type=\"text/javascript\"></script>\n", item.Path);
}
return new HtmlString(sb.ToString());
}
public class ResourceInclude
{
public string Path { get; set; }
public int Priority { get; set; }
}
}//end class
}// end namespace
Образец на PartialView: - @Html.RequireBundleStyles( "~/пучки/FileUpload/самозагрузки/BasicPlusUI/CSS" ); @Html.RequireBundleScripts( "~/пучки/FileUpload/самозагрузки/BasicPlusUI/JS" );
Образец на MasterPage: - @Html.EmitRequiredBundleStyles()
Ответ 8
Используйте @using(Html.Delayed()){ ...your content... }
расширения из ответа fooobar.com/questions/26763/..., чтобы отобразить любой контент (сценарии или только HTML) позже на странице. Внутренний Queue
должен обеспечить правильный порядок.
Ответ 9
Эта функциональность также реализована в ClientDependency.Core.Mvc.dll. Он предоставляет html-помощники: @Html.RequiresJs и @Html.RenderJsHere(). Пакет Nuget: ClientDependency-Mvc
Ответ 10
Вы можете создать новую страницу Layout
и обернуть PartialView внутри полного представления, который отвечает за рендеринг содержимого, а также за любые разделы библиотеки.
Например, допустим, у меня есть следующий код:
HomeController.cs
[HttpGet]
public ActionResult About()
{
var vm = new AboutViewModel();
return View("About", vm);
}
Когда визуализируется полноэкранное представление, оно обычно создается путем слияния двух файлов:
About.cshtml
@model AboutViewModel
@{
ViewBag.Title = "About CSHN";
}
<h3>@ViewBag.Title</h3>
@section Styles {
<style> /* style info here */ </style>
}
@section Scripts {
<script> /* script info here */ </script>
}
_Layout.cshtml
(или что-то, что указано в _ViewStart или переопределено на странице)
<!DOCTYPE html>
<html>
<head>
@RenderSection("Styles", false)
<title>@ViewBag.Title</title>
</head>
<body>
@RenderBody()
@RenderSection("scripts", false)
</body>
</html>
Теперь предположим, что вы хотели Рендер About.cshtml
как частичным видом, возможно, модальное окно в ответ на AJAX вызова. Цель состоит в том, чтобы возвращать только содержимое, указанное на странице about, скриптах и всех, без всякой навороты, включенной в _Layout.cshtml
мастера _Layout.cshtml
(например, полный <html>
документ).
Вы можете попробовать это так, но он не будет поставляться ни с одним из блоков секций:
return PartialView("About", vm);
Вместо этого добавьте упрощенную страницу компоновки следующим образом:
_PartialLayout.cshtml
<div>
@RenderBody()
@RenderSection("Styles", false)
@RenderSection("scripts", false)
</div>
Или для поддержки модального окна:
_ModalLayout.cshtml
<div class="modal modal-page fade" tabindex="-1" role="dialog" >
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title">@ViewBag.Title</h4>
</div>
<div class="modal-body">
@RenderBody()
@RenderSection("Styles", false)
@RenderSection("scripts", false)
</div>
<div class="modal-footer">
<button type="button" class="btn btn-inverse" data-dismiss="modal">Dismiss</button>
</div>
</div>
</div>
</div>
Затем вы можете указать пользовательский Мастер-вид в этом контроллере или любом другом обработчике, который вы хотите отображать содержимое и сценарии представления одновременно
[HttpGet]
public ActionResult About()
{
var vm = new AboutViewModel();
return !Request.IsAjaxRequest()
? View("About", vm)
: View("About", "~/Views/Shared/_ModalLayout.cshtml", vm);
}
Ответ 11
Здесь написано мое решение часто задаваемых вопросов: "Как вводить разделы из частичных представлений в главные или основные макеты для asp.net mvc?". Если вы выполните поиск по stackoverflow по ключевым словам "раздел + частичный", вы получите довольно большой список связанных вопросов и ответы, но ни один из них не кажется мне элегантным с помощью грамматики бритвенного двигателя. Поэтому я просто посмотрю на двигатель Razor, посмотрим, может ли быть какое-то лучшее решение этого вопроса.
К счастью, мне было интересно, как движок Razor делает компиляцию для файла шаблона вида (*.cshtml, *.vbhtml). (Я объясню позже), ниже мой код решения, который я считаю довольно простым и изящным в использовании.
namespace System.Web.Mvc.Html
{
public static class HtmlHelperExtensions
{
/// <summary>
/// 确保所有视图,包括分部视图(PartialView)中的节(Section)定义被按照先后顺序追加到最终文档输出流中
/// </summary>
public static MvcHtmlString EnsureSection(this HtmlHelper helper)
{
var wp = (WebViewPage)helper.ViewDataContainer;
Dictionary<string, WebPages.SectionWriter> sw = (Dictionary<string, WebPages.SectionWriter>)typeof(WebPages.WebPageBase).GetProperty("SectionWriters", Reflection.BindingFlags.NonPublic | Reflection.BindingFlags.Instance).GetValue(wp);
if (!helper.ViewContext.HttpContext.Items.Contains("SectionWriter"))
{
Dictionary<string, Stack<WebPages.SectionWriter>> qss = new Dictionary<string, Stack<WebPages.SectionWriter>>();
helper.ViewContext.HttpContext.Items["SectionWriter"] = qss;
}
var eqs = (Dictionary<string, Stack<WebPages.SectionWriter>>)helper.ViewContext.HttpContext.Items["SectionWriter"];
foreach (var kp in sw)
{
if (!eqs.ContainsKey(kp.Key)) eqs[kp.Key] = new Stack<WebPages.SectionWriter>();
eqs[kp.Key].Push(kp.Value);
}
return MvcHtmlString.Create("");
}
/// <summary>
/// 在文档流中渲染指定的节(Section)
/// </summary>
public static MvcHtmlString RenderSectionEx(this HtmlHelper helper, string section, bool required = false)
{
if (helper.ViewContext.HttpContext.Items.Contains("SectionWriter"))
{
Dictionary<string, Stack<WebPages.SectionWriter>> qss = (Dictionary<string, Stack<WebPages.SectionWriter>>)helper.ViewContext.HttpContext.Items["SectionWriter"];
if (qss.ContainsKey(section))
{
var wp = (WebViewPage)helper.ViewDataContainer;
var qs = qss[section];
while (qs.Count > 0)
{
var sw = qs.Pop();
var os = ((WebViewPage)sw.Target).OutputStack;
if (os.Count == 0) os.Push(wp.Output);
sw.Invoke();
}
}
else if (!qss.ContainsKey(section) && required)
{
throw new Exception(string.Format("'{0}' section is not defined.", section));
}
}
return MvcHtmlString.Create("");
}
}
}
Использование: Для того, чтобы использовать код довольно просто, а также, и это выглядит почти такой же стиль обычных. Он также поддерживает любые уровни для вложенных частичных представлений. то есть. У меня есть цепочка шаблона представления: _ViewStart. cshtml-> макет. cshtml-> index. cshtml-> [head.cshtml, foot.cshtml] → ad.cshtml.
В layout.cshtml у нас есть:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>@ViewBag.Title - @ViewBag.WebSetting.Site.WebName</title>
<base href="@ViewBag.Template/" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta http-equiv="Cache-Control" content="no-siteapp" />
<meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1.0, user-scalable=0,user-scalable=no">
<meta name="format-detection" content="telephone=no">
<meta name="renderer" content="webkit">
<meta name="author" content="Taro Technology Co.,LTD" />
<meta name="robots" content="index,follow" />
<meta name="description" content="" />
<meta name="keywords" content="" />
<link rel="alternate icon" type="@ViewBag.WebSetting.Site.WebFavIcon" href="@ViewBag.WebSetting.Site.WebFavIcon">
@Html.RenderSectionEx("Head")
</head>
<body>
@RenderBody()
@Html.RenderSectionEx("Foot")
</body>
</html>
Ответ 12
Для тех, кто ищет версию Aspnet Core 2.0:
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Http;
public static class HttpContextAccessorExtensions
{
public static string RequireScript(this IHttpContextAccessor htmlContextAccessor, string path, int priority = 1)
{
var requiredScripts = htmlContextAccessor.HttpContext.Items["RequiredScripts"] as List<ResourceInclude>;
if (requiredScripts == null) htmlContextAccessor.HttpContext.Items["RequiredScripts"] = requiredScripts = new List<ResourceInclude>();
if (requiredScripts.All(i => i.Path != path)) requiredScripts.Add(new ResourceInclude() { Path = path, Priority = priority });
return null;
}
public static HtmlString EmitRequiredScripts(this IHttpContextAccessor htmlContextAccessor)
{
var requiredScripts = htmlContextAccessor.HttpContext.Items["RequiredScripts"] as List<ResourceInclude>;
if (requiredScripts == null) return null;
StringBuilder sb = new StringBuilder();
foreach (var item in requiredScripts.OrderByDescending(i => i.Priority))
{
sb.AppendFormat("<script src=\"{0}\" type=\"text/javascript\"></script>\n", item.Path);
}
return new HtmlString(sb.ToString());
}
public class ResourceInclude
{
public string Path { get; set; }
public int Priority { get; set; }
}
}
Добавьте в свой макет после вызова секции рендеринга скриптов:
@HttpContextAccessor.EmitRequiredScripts()
И по вашему частичному мнению:
@inject IHttpContextAccessor HttpContextAccessor
...
@HttpContextAccessor.RequireScript("/scripts/moment.min.js")