ASP.NET 6中如何向自定义函数传递HtmlContent?
MVC5迁移.NET6:@helper转@functions的正确实现
问题描述
将MVC5应用迁移至.NET 6时,原使用@helper定义的可接收HTML内容的InfoRow辅助方法:
@helper InfoRow(string title, Func<dynamic, HelperResult> content) { <div class="row"> <label class="col-md-3 col-form-label">@title</label> <div class="col"> <span class="form-control-plaintext"> @content(null) </span> </div> </div> }
调用方式:
@InfoRow("Notes", @<span><b>@row.Number</b> new notes</span>)
尝试改为.NET 6的@functions实现,但不确定是否可行:
@functions { private void InfoRow(string title, IHtmlContent content) { <div class="row"> <label class="col-md-3 col-form-label">@title</label> <div class="col"> <span class="form-control-plaintext"> @content </span> </div> </div> } }
解答
现有实现不可行
你的void类型函数无法在Razor视图中直接输出HTML内容——Razor编译时不会处理void方法内的标记,这些代码不会被渲染到页面上。
正确实现方式
需要让函数返回IHtmlContent(或其子类型HelperResult),并使用RenderFragment作为内容参数(兼容原@<xxx>的调用语法),以下是两种可行方案:
方案1:使用TagBuilder构建HTML(类型安全,推荐)
@functions { private IHtmlContent InfoRow(string title, RenderFragment content) { // 构建外层row容器 var rowDiv = new TagBuilder("div"); rowDiv.AddCssClass("row"); // 构建label var label = new TagBuilder("label"); label.AddCssClass("col-md-3 col-form-label"); label.InnerHtml.Append(title); rowDiv.InnerHtml.AppendHtml(label); // 构建col容器 var colDiv = new TagBuilder("div"); colDiv.AddCssClass("col"); // 构建plaintext span var textSpan = new TagBuilder("span"); textSpan.AddCssClass("form-control-plaintext"); textSpan.InnerHtml.AppendHtml(content); colDiv.InnerHtml.AppendHtml(textSpan); rowDiv.InnerHtml.AppendHtml(colDiv); return rowDiv; } }
方案2:使用HelperResult直接写入输出流
@functions { private HelperResult InfoRow(string title, RenderFragment content) { return new HelperResult(writer => { writer.Write(@"<div class=""row"">"); writer.Write(@"<label class=""col-md-3 col-form-label"">"); writer.Write(title); writer.Write(@"</label>"); writer.Write(@"<div class=""col"">"); writer.Write(@"<span class=""form-control-plaintext"">"); // 渲染传入的HTML内容 content(writer); writer.Write(@"</span>"); writer.Write(@"</div>"); writer.Write(@"</div>"); }); } }
调用方式
两种方案的调用方式和原@helper完全一致:
@InfoRow("Notes", @<span><b>@row.Number</b> new notes</span>)
内容的提问来源于stack exchange,提问作者Echilon
相关产品推荐
相关产品推荐

