How to render a Razor template inside a custom TagHelper in ASP.NET Core?
Asked Answered
A

2

13

I am creating a custom HTML Tag Helper:

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);
        }
    }

How to render a partial view programatically an get the rendered content as a string inside TagHelper.ProcessAsync ?
Should I request the injection of an IHtmlHelper ?
Is it possible to get a reference to the razor engine ?

Amorete answered 5/11, 2016 at 12:6 Comment(0)
A
26

It is possible to request the injection of an IHtmlHelper in the custom TagHelper:

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);
        }
    }

The IHtmlHelper instance provided is not ready for use and it is necessary to contextualize it, hence the (html as IViewContextAware).Contextualize(ViewContext); statement.

The IHtmlHelper.Partial method can then be used to generate the template.

Credit goes to frankabbruzzese for his comment on Facility for rendering a partial template from a tag helper.

Amorete answered 5/11, 2016 at 21:12 Comment(2)
Is this considered bad practice? Should we be using IHtmlHelper in our TagHelpers?Yonah
@Yonah actually it might be a bad practice since View Components exist.Amorete
O
6

Adding a small (and yet important) addition to Chedy's answer (which is the right one), This code can be used in a base class:

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);
    }
}

So, inheriting PartialTagHelperBase can help rendering partial views in a very simple and effective way:

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

        output.PreContent.AppendHtml(someContent);
Orphism answered 28/8, 2019 at 22:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.