ASP.NET Core MVC自定义HtmlHelper如何自动加载关联CSS/JS资源
问题原因
@section 是Razor视图编译阶段识别的指令,你在运行时动态拼接字符串输出的内容不会被ASP.NET Core解析为Razor指令,因此无法生效。
实现方案
我们可以通过HttpContext.Items做资源加载标记,避免同一页面多次调用组件时重复引入资源,直接输出<link>和<script>标签即可,以下是修改后的代码:
using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.ViewFeatures; using System; using System.Linq.Expressions; using System.Text; using Microsoft.AspNetCore.Html; public static class HtmlHelpers { public static IHtmlContent MyDropdown<TModel>(this IHtmlHelper<TModel> htmlHelper, Expression<Func<TModel, DropdownViewModel>> expression) { var builder = new StringBuilder(@"<div class=""dropdown"">"); // 你的下拉框逻辑代码写在这里 builder.AppendLine("</div>"); var httpContext = htmlHelper.ViewContext.HttpContext; var urlHelper = htmlHelper.Url ?? new UrlHelper(htmlHelper.ViewContext); // 处理CSS资源引入,避免重复加载 const string styleKey = "MyDropdown_Style_Loaded"; if (!httpContext.Items.ContainsKey(styleKey)) { var cssPath = urlHelper.Content("~/css/dropdown.css"); builder.AppendLine($"<link rel=\"stylesheet\" href=\"{cssPath}\" />"); httpContext.Items[styleKey] = true; } // 处理JS资源引入,避免重复加载 const string scriptKey = "MyDropdown_Script_Loaded"; if (!httpContext.Items.ContainsKey(scriptKey)) { var jsPath = urlHelper.Content("~/js/dropdown.js"); builder.AppendLine($"<script src=\"{jsPath}\"></script>"); httpContext.Items[scriptKey] = true; } return new HtmlString(builder.ToString()); } }
补充说明
- 如果你的站点要求CSS必须放在
<head>标签、JS必须放在<body>底部,你可以额外在布局页预留占位符:- 在布局页的
<head>里加上@Html.Raw(ViewData["CustomStyles"]) - 在布局页的
</body>前加上@Html.Raw(ViewData["CustomScripts"]) - 在HtmlHelper扩展里把资源内容存到
htmlHelper.ViewContext.ViewData对应的键里,而不是直接拼到组件的HTML后即可,这种方式仅需要一次布局页修改,无需每个调用页面手动加资源引用。
- 在布局页的
- 上述代码已经修正了你原代码里的拼写错误:
Expressoion改为Expression、DropdownViewModle改为DropdownViewModel,补全了缺失的分号。
内容的提问来源于stack exchange,提问作者3xGuy
相关产品推荐
相关产品推荐

