One of the best features added to ASP.NET Core Razor is Tag Helpers. These can be added to standard HTML elements, and can participate in their rendering. Alternatively, they can be entirely new elements. Functionally, they are similar to the Html Helpers of previous version of ASP.NET, in that they can be used to easily create forms and other elements.
One of the big advantages of Tag Helpers over Html Helpers is their syntax - they look like standard HTML attributes, so they're easy to edit in a standard HTML editor. Unfortunately there are some C# structures that don't currently have a Tag Helper equivalent.
In this short post, I'll create a simple tag helper to conditionally render content in a Razor page, equivalent to adding an @if
statement to standard Razor.
The Razor @if
statement
As an example, I am going to create tag helpers for writing the following example razor:
@if(true)
{
<p>Included</p>
}
@if(false)
{
<p>Excluded</p>
}
This code renders the first <p>
but not the second. Pretty self explanatory, but it can be jarring to read code that switches between C# and markup in this fashion. It's especially obvious here as the syntax highlighter I use doesn't understand Razor, just markup. That's one of the selling points of Tag Helpers - making your Razor pages easier to understand for standard HTML parsers.
The Tag Helper version
The final result we're aiming for is the following:
<if include-if="true">
<p>Included</p>
</if>
<if include-if="false">
<p>Excluded</p>
</if>
As we are are writing a custom Tag Helper we can also easily support the alternative approach, where we can either include or exclude the inner markup based on a variable:
<if include-if="true">
<p>Included</p>
</if>
<if exclude-if="true">
<p>Excluded</p>
</if>
The inner markup will only be rendered if the include-if
attribute evaluates to true
, and the exclude-if
attribute evaluates to false
.
Let's take a look at the implementation.
The IfTagHelper
The IfTagHelper
implementation is pretty simple. We inherit from the TagHelper
class, and expose two properties as attributes on the element - Include
and Exclude
. We override the Process()
function, and conditionally suppress the output content if necessary:
public class IfTagHelper : TagHelper
{
public override int Order => -1000;
[HtmlAttributeName("include-if")]
public bool Include { get; set; } = true;
[HtmlAttributeName("exclude-if")]
public bool Exclude { get; set; } = false;
public override void Process(TagHelperContext context, TagHelperOutput output)
{
// Always strip the outer tag name as we never want <if> to render
output.TagName = null;
if (Include && !Exclude)
{
return;
}
output.SuppressOutput();
}
}
The Process
function is where we control whether to render the inner content or not.
First, whether or not we render the inner content, we want to ensure the <if>
attribute is not rendered to the final output. We can achieve this by setting output.TagName = null;
.
Next, we check whether we should render the content inside the <if>
tag or not. If not, then we just return from the tag handler, as no further processing is required. The inner content will be rendered as normal.
If we don't want to render the contents, then we need to suppress the rendering by calling output.SuppressOutput();
. This ensures none of the content within the <if>
tag is rendered to the output.
The result
So, finally, lets take a look at how this all plays out - for the following Razor:
<if>
<p>Included 1</p>
</if>
<if include-if="1 == 1">
<p>Included 2</p>
</if>
<if exclude-if="false">
<p>Included 3</p>
</if>
<if include-if="false">
<p>Excluded 1</p>
</if>
<if exclude-if="1 == 1">
<p>Excluded 2</p>
</if>
Note that the content inside the include-if
or exclude-if
attributes is C# - you can include any C# expression there that evaluates to a boolean. The following HTML will be rendered:
<p>Included 1</p>
<p>Included 2</p>
<p>Included 3</p>
An alternative tag helper using attributes
In this example, I created a standalone <if>
Tag Helper that you can wrap around content that you want to conditionally show or hide. However, you may prefer to have a Tag Helper that you attach as an attribute to standard HTML elements. For example:
<p include-if="1 == 1">Included</p>
<p exclude-if="true">Excluded</p>
This is easy to achieve with a few simple modifications, but I'll leave it as an exercise to the reader. If you just want to see the code, I have an example on GitHub, or you can check out the example in the ASP.NET Core documentation which does exactly this!
Summary
This simple Tag Helper can be used to reduce the amount of C# in your Razor files, making it easier to read and edit with HTML editors. You can find the code for this post on GitHub.