A @section Scripts
block does not work when placed in a partial view in ASP.NET. Unfortunately, you don't get any error messages if you try to add the section to a partial -- it just does nothing. In many cases, having a scripts section in a partial view would be an anti-pattern, since the partial can be rendered an unknown number of times. However, there are times when I believe a scripts section is warranted in a partial, particularly when you're trying to create dynamic JavaScript based on the model passed into the partial view. While you can't just use the actual @section Scripts
in a partial view, you can add some HTML helper extensions to accomplish the same thing.
Below is the code to accomplish this functionality -- here are the helper extension methods that you'd add into a C# file in your project:
using System;
using System.Linq;
using System.Text.Encodings.Web;
using System.Text.RegularExpressions;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.Rendering;
public static class HtmlHelperExtensions
{
private const string _partialViewScriptItemPrefix = "scripts_";
public static IHtmlContent PartialSectionScripts(this IHtmlHelper htmlHelper, Func<object, HelperResult> template)
{
htmlHelper.ViewContext.HttpContext.Items[_partialViewScriptItemPrefix + Guid.NewGuid()] = template;
return new HtmlContentBuilder();
}
public static IHtmlContent RenderPartialSectionScripts(this IHtmlHelper htmlHelper)
{
var partialSectionScripts = htmlHelper.ViewContext.HttpContext.Items.Keys
.Where(k => Regex.IsMatch(
k.ToString(),
"^" + _partialViewScriptItemPrefix + "([0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12})$"));
var contentBuilder = new HtmlContentBuilder();
foreach (var key in partialSectionScripts)
{
var template = htmlHelper.ViewContext.HttpContext.Items[key] as Func<object, HelperResult>;
if (template != null)
{
var writer = new System.IO.StringWriter();
template(null).WriteTo(writer, HtmlEncoder.Default);
contentBuilder.AppendHtml(writer.ToString());
}
}
return contentBuilder;
}
}
PartialSectionScripts
is called in the partial view in place of where you would otherwise be using @section Scripts
.
RenderPartialSectionScripts
would typically be called in your shared layout, e.g. _Layout.cshtml in the standard scaffolded projects, and will render any scripts added in partials via the PartialSectionScripts
method call.
Here's an example from a partial view of using PartialSectionScripts
:
@Html.PartialSectionScripts(
@<script>
alert('Hello from the partial view!');
</script>
)
And the example with the RenderPartialSectionScripts
line added in your shared layout, where you would likely want to place it after your RenderSection
and before the end of the body:
@*...*@
@RenderSection("Scripts", required: false)
@Html.RenderPartialSectionScripts()
</body>
</html>