You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core MVC非Blazor下如何实现可复用HTML组件

ASP.NET Core MVC 没有 Blazor 原生的 RenderFragment 类型,但有成熟方案可以实现完全一致的可复用组件效果,其中最匹配你需求的是 Tag Helper 方案,语法和你想要的组件写法几乎无差别。


方案1:Tag Helper(最推荐,语法最接近Blazor组件)

这是最贴合你预期使用方式的实现,最终调用语法和你写的Blazor组件示例完全一致,不需要写复杂的调用逻辑,非开发背景的设计人员也能快速看懂。

  1. 编写自定义Tag Helper类,不要使用Blazor专属的RenderFragment类型,直接通过内置API读取标签包裹的子内容即可:
// 标记目标标签为<card>,支持自闭合和正常闭合写法
[HtmlTargetElement("card", TagStructure = TagStructure.NormalOrSelfClosing)]
public class CardTagHelper : TagHelper
{
    // 对应组件的Title参数
    public string Title { get; set; }

    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        // 读取标签包裹的所有子内容,等效于Blazor的ChildContent
        var innerContent = await output.GetChildContentAsync();
        
        // 配置输出的外层标签和样式
        output.TagName = "div";
        output.Attributes.SetAttribute("class", "card card-px-0 shadow-sm");

        // 拼接完整的卡片结构,后续Bootstrap版本升级只需要改这里的结构
        output.Content.SetHtmlContent(
            new HtmlContentBuilder()
                .AppendHtml($@"
                <div class=""card-header"">
                    <h3 class=""card-title"">{Title}</h3>
                    <div class=""card-toolbar"">
                        <button type=""button"" class=""btn btn-sm btn-light"">Action</button>
                    </div>
                </div>
                <div class=""card-body"">")
                .AppendHtml(innerContent)
                .AppendHtml(@"
                </div>
                <div class=""card-footer"">Footer</div>")
        );
    }
}
  1. 在视图共享导入文件_ViewImports.cshtml中添加Tag Helper注册,替换成你自己的项目程序集名称即可:
@addTagHelper *, YourProjectAssemblyName
  1. 之后在任意视图中可以直接用你想要的标签语法调用:
<card title="Section Title">
    <p>I'm the body and would render inside the `ChildContent` area!</p>
</card>

如果需要实现多个命名内容片段(类似Blazor的具名RenderFragment),只需要新增对应嵌套标签的Tag Helper即可,比如自定义card-footer标签传入自定义页脚内容,扩展非常灵活。


方案2:局部视图(Partial View)+ 模板委托

如果不想编写独立的Tag Helper类,也可以用局部视图配合Razor模板委托实现内容传入:

  1. 新建局部视图Views/Shared/_Card.cshtml,定义接收的参数:
@model CardComponentModel
<div class="card card-px-0 shadow-sm">
    <div class="card-header">
        <h3 class="card-title">@Model.Title</h3>
        <div class="card-toolbar">
            <button type="button" class="btn btn-sm btn-light">Action</button>
        </div>
    </div>
    <div class="card-body">
        @* 渲染传入的内容模板 *@
        @Model.ContentTemplate(null)
    </div>
    <div class="card-footer">Footer</div>
</div>
  1. 定义对应的参数模型:
public class CardComponentModel
{
    public string Title { get; set; }
    // 用Razor原生的模板委托替代RenderFragment
    public Func<dynamic, IHtmlContent> ContentTemplate { get; set; }
}
  1. 视图中调用方式如下:
@{
    var cardData = new CardComponentModel
    {
        Title = "Section Title",
        ContentTemplate = @<p>I'm the body content!</p>
    };
}
<partial name="_Card" model="cardData" />

这个方案的缺点是调用语法不如Tag Helper直观,适合结构非常简单的复用场景。


其他方案说明

  • 你之前尝试的ViewComponent无法实现效果,核心原因是RenderFragment是Blazor专属的类型,MVC视图渲染管线不识别这个类型。如果一定要用ViewComponent,可以把ContentTemplate的类型换成IHtmlContent,调用时手动将子内容转为HTML字符串传入,但写法非常繁琐,远不如Tag Helper简洁,不推荐使用。
  • 你提到的@helper语法在新版ASP.NET Core中已经被正式移除,不要在新项目中使用。

内容的提问来源于stack exchange,提问作者Scott Salyer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 06:09:18