In the Rendering a tag helper inside another tag helper post, I showed how it was possible to instantiate a tag helper, to run its
Process method and to get the generated result as a string.
Recently, after doing some investigation about the tag helper rendering process I had some insights about how to create
TagHelperContext objects as well as how to leverage existing behaviors to get the generated content as a string.
Now let’s review this chunk of code step by step.
Creating the TagHelperOutput
TagHelperOutput object gets populated by the generated content inside the tag helper’s
We need to supply some arguments to the constructor of the
TagHelperOutput class to create one:
- The TagName of the tag being rendered
- The list of html attributes related to the tag being rendered
- A callback that asynchronously returns any eventual child content contained inside the tag being rendered
The razor template engine seems to provide the
TagName value for ‘standard’ html tag helpers such as the
img tag helpers. So it is the responsibility of the creator of the
TagHelperOutput to provide this value. Nevertheless it can be safe to ignore this argument for custom tag helpers that sets their
TagName by them selves.
The attribute list argument is straightforward; just supply the list of desired html attributes.
The callback argument is generated by the razor template engine when rendering nested tag helpers. It should contain code that generates child content and that runs any nested tag helpers.
We can safely assume that it is safe to provide an async function that returns empty
TagHelperContent when the tag helper does not contain child content.
Finally, the razor template engine also sets the
TagMode property on the
TagHelperOutput object. It is wise to do so when creating
Creating the TagHelperContext
The responsibility of the
TagHelperContext is to contain data that is going to be passed from parent to child tag helpers when they are Processed.
In the previous example, we just used the context object provided by the razor template engine. But let’s see how to create one still.
The constructor for
TagHelperContext takes the following arguments:
- The same attribute list used for creating the
- An Items
Dictionary<object, object>that contains the data passed along with the context
- A unique identifier for the rendering scope
The first two arguments are straightforward.
The last argument is used internally by the ASP.NET Core framework for some caching mechanism and is provided by the razor template engine, furthermore the value generated of the unique Id generated by razor seems to be a Guid striped of its hyphens(726e2629c3b34a6b92dd8436f55ad968 for example). So I think it is OK to provide a bogus value since we are not soliciting the caching behavior when rendering tag helpers programmatically.
Finally, I would like to point out that the
TagHelperContext instance might not be used if there are no nested content involved.
Getting the generated content as a string
renderInnerTagHelper method, the tag helper
output is manually converted into a string and an additional
renderHtmlAttributes method is defined to generate the html attributes.
TagHelperOutput class implements the
IHtmlContent interface and provides an implementation for the
WriteTo method that writes the output content into a supplied
TagHelperOutput.WriteTo takes two arguments:
TextWriterobject, here we just pass a new
HtmlEncoderobject, that we can get by dependency injection
All we have to do after calling
WriteTo is to read the results from the supplied
Clearly, this is the way to go to get the rendered content.
Revisiting the previous example
The following is the updated
renderInnerTagHelper method, you can see that we took into account the previous guidelines:
The full code is, of course, available in the RenderingTagHelperInsideAnother Github repository.