How to render a Razor template inside a custom TagHelper in ASP.NET Core?
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);
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.