如何在 ASP.NET Core 的自定义 TagHelper 中呈现 Razor 模板?

Posted

技术标签:

【中文标题】如何在 ASP.NET Core 的自定义 TagHelper 中呈现 Razor 模板?【英文标题】:How to render a Razor template inside a custom TagHelper in ASP.NET Core? 【发布时间】:2017-03-19 04:41:23 【问题描述】:

我正在创建一个自定义 html 标签助手:

public class CustomTagHelper : TagHelper
    
        [HtmlAttributeName("asp-for")]
        public ModelExpression DataModel  get; set; 

        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        
            string content = RazorRenderingService.Render("TemplateName", DataModel.Model);
            output.Content.SetContent(content);
        
    

如何以编程方式呈现部分视图并将呈现的内容作为字符串在 TagHelper.ProcessAsync 中获取? 我应该请求注入 IHtmlHelper 吗? 是否可以参考剃须刀引擎?

【问题讨论】:

【参考方案1】:

可以在自定义TagHelper中请求注入IHtmlHelper:

public class CustomTagHelper : TagHelper
    
        private readonly IHtmlHelper html;

        [HtmlAttributeName("asp-for")]
        public ModelExpression DataModel  get; set; 

        [HtmlAttributeNotBound]
        [ViewContext]
        public ViewContext ViewContext  get; set; 

        public CustomTagHelper(IHtmlHelper htmlHelper)
        
            html = htmlHelper;
        
        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        
            //Contextualize the html helper
            (html as IViewContextAware).Contextualize(ViewContext);

            var content = await html.PartialAsync("~/Views/path/to/TemplateName.cshtml", DataModel.Model);
            output.Content.SetHtmlContent(content);
        
    

提供的IHtmlHelper 实例尚未准备好使用,需要对其进行上下文化,因此(html as IViewContextAware).Contextualize(ViewContext); 语句。

然后可以使用IHtmlHelper.Partial 方法生成模板。

感谢 frankabbruzzese 他对 Facility for rendering a partial template from a tag helper 的评论。

【讨论】:

这被认为是不好的做法吗?我们应该在 TagHelpers 中使用 IHtmlHelper 吗? @Dave 实际上这可能是一个不好的做法,因为 View Components 存在。【参考方案2】:

在 Chedy 的答案中添加一个小(但很重要)的补充(这是正确的),此代码可以在基类中使用:

public class PartialTagHelperBase : TagHelper

    private IHtmlHelper                         m_HtmlHelper;

    public ShopStreetTagHelperBase(IHtmlHelper htmlHelper)
    
        m_HtmlHelper = htmlHelper;
    

    [HtmlAttributeNotBound]
    [ViewContext]
    public ViewContext ViewContext  get; set; 

    protected async Task<IHtmlContent> RenderPartial<T>(string partialName, T model)
    
        (m_HtmlHelper as IViewContextAware).Contextualize(ViewContext);

        return await m_HtmlHelper.PartialAsync(partialName, model);
    

所以,继承PartialTagHelperBase可以帮助以一种非常简单有效的方式渲染部分视图:

        IHtmlContent someContent = await RenderPartial<SomeModel>("_SomePartial", new SomeModel());

        output.PreContent.AppendHtml(someContent);

【讨论】:

以上是关于如何在 ASP.NET Core 的自定义 TagHelper 中呈现 Razor 模板?的主要内容,如果未能解决你的问题,请参考以下文章

如何创建不依赖于 ASP.NET Core 声明的自定义 Authorize 属性?

如何通过 ASP.NET Core 中的 api 控制器更新 IdentityUser 的自定义属性?

ASP.Net-Core 中的自定义身份验证

ASP.Net Core 的自定义承载令牌授权

带有取消令牌的自定义 ASP.NET Core 中间件

ASP.NET Core 2.2 Razor 页面中的自定义路由