When creating a custom TagHelper it would be convenient to be able to render an existing partial view programatically and capture the rendered result in a string or an HtmlContent object inside the TagHelper.Process method.
For example, consider the following hypothetical custom TagHelper
`
public class CustomTagHelper : TemplateRenderingTagHelper
{
[HtmlAttributeName("asp-for")]
public ModelExpression DataModel { get; set; }
public override Task Process(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "div";
var renderedContent = HtmlHelper.Partial("~/Views/Shared/path/to/Template.cshtml");
output.Content.SetHtmlContent(renderedContent);
}
}`
This tag helper inherits from the hypothetical TemplateRenderingTagHelper abstract class, this class would look like this:
`public abstract TemplateRenderingTagHelper : TagHelper
{
protected IHtmlHelper HtmlHelper { get; set; }
public TemplateRenderingTagHelper()
{
//Get a IHtmlHelper instance
HtmlHelper = BuildAnIHtmlHelper();
}
}
`
As you can see this class makes available the HtmlHelper property for its sub classes, the HtmlHelper.Partial (or PartialAsync) can then be used to generate a template.
Even if it is possible to call @Html.RenderPartial directly from the view, it is cleaner to factor the rendering inside the TagHelper.Process method especially if the rendering requires some preprocessing.
Consider the following TagHelper.Process example:
`
...
[HtmlAttributeName("asp-for")]
public ModelExpression DataModel { get; set; }
...
public override Task Process(TagHelperContext context, TagHelperOutput output)
{
// Preprocessing on the model
var model = SomeProcessingOn(DataModel.Model);
// Building a Custom ViewData Dictionary
var ViewData = BuildCustomViewDataDictWithCustomizedMetadata();
output.TagName = "div";
var renderedContent = HtmlHelper.Partial("~/Views/Shared/path/to/Template.cshtml", model, ViewData)
output.Content.SetHtmlContent(renderedContent);
}`
@MissaouiChedy ,
Actually, you can use an HtmlHelper from within a TagHelper also now, with no need for further features:
IHtmlHelperargument to the constructor of your TagHelper, say: IHtmlHelper html, so that a fresh Html instance is injected when your TagHelper is created. html. The injected TagHlper is "neutral", not specific for your View, so you have to "contextualize" it for the current View Viecontext as explained in the steps below [HtmlAttributeNotBound]
[ViewContext]
public ViewContext ViewContext { get; set; }
It will be automatically bound to your View ViewContext
(html as IViewContextAware).Contextualize(ViewContext );
Done! Now you have a working HtmlHelper.
@frankabbruzzese
Yes in fact it works.
I tried previously to get an IHtmlHelper by using dependency injection, but I got an exception whenever I called one of its methods.
It turned out that I missed the contextualization part.
Most helpful comment
@MissaouiChedy ,
Actually, you can use an HtmlHelper from within a TagHelper also now, with no need for further features:
IHtmlHelperargument to the constructor of your TagHelper, say:IHtmlHelper html, so that a fresh Html instance is injected when your TagHelper is created.html. The injected TagHlper is "neutral", not specific for your View, so you have to "contextualize" it for the current View Viecontext as explained in the steps belowIt will be automatically bound to your View ViewContext
Done! Now you have a working HtmlHelper.