How to Initialize TagHelpers in ASP.NET Core with Shared Data

By Tan Lee Published on Apr 16, 2025  47
ASP.NET Core’s Razor engine is packed with superpowers. One of the most underrated? The ability to globally initialize TagHelpers with shared data giving you centralized control over UI behavior without repetitive markup or logic.

In this article, we’ll walk through how to create a custom FeatureToggleTagHelper that hides or shows sections of a page based on feature flags and we’ll inject those flags globally using a TagHelper initializer.

Say you have a feature toggle system maybe you're using something like LaunchDarkly, Azure App Configuration, or a simple in-memory dictionary. You want to conditionally render parts of your UI based on whether a feature is enabled.

Create the TagHelper

Here’s a FeatureToggleTagHelper that checks a feature-name attribute and decides whether to render the enclosed content.

using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Razor.TagHelpers;

namespace MyApp.TagHelpers;

[HtmlTargetElement("feature-toggle")]
public class FeatureToggleTagHelper : TagHelper
{
    [HtmlAttributeName("feature-name")]
    public string FeatureName { get; set; } = "";

    [HtmlAttributeNotBound]
    public IDictionary<string, bool> FeatureFlags { get; set; } = new Dictionary<string, bool>();

    public override Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        if (FeatureFlags.TryGetValue(FeatureName, out var isEnabled) && isEnabled)
        {
            // Feature is enabled, render as normal
        }
        else
        {
            output.SuppressOutput(); // Hide the content
        }

        return Task.CompletedTask;
    }
}

Usage in a Razor view:

<feature-toggle feature-name="NewDashboard">
    <div class="alert alert-info">
        🎉 The new dashboard is now live!
    </div>
</feature-toggle>

If the feature "NewDashboard" is enabled, the message appears. If not, the block is removed from the final HTML entirely.

Create the Initializer

To avoid manually injecting feature flags into every usage, we’ll globally initialize the TagHelper using the ITagHelperInitializer<T> interface.

public class FeatureToggleTagHelperInitializer(
    IDictionary<string, bool> featureFlags)
    : ITagHelperInitializer<FeatureToggleTagHelper>
{
    public void Initialize(FeatureToggleTagHelper helper, ViewContext context)
    {
        helper.FeatureFlags = featureFlags;
    }
}

This allows us to inject the entire dictionary of feature flags into every instance of FeatureToggleTagHelper.

Register the Initializer

In Program.cs, register your initializer with the service collection:

var featureFlags = new Dictionary<string, bool>
{
    { "NewDashboard", true },
    { "BetaFeature", false }
};

builder.Services.AddSingleton<ITagHelperInitializer<FeatureToggleTagHelper>>(
    new FeatureToggleTagHelperInitializer(featureFlags)
);

Of course, you could take this a step further by resolving the flags from a config provider or remote feature management service.

Given the above setup, your Razor view might produce the following HTML:

<div class="alert alert-info">
    🎉 The new dashboard is now live!
</div>

If "NewDashboard" is set to false, the entire block is stripped out no wasted DOM, no extra logic in the view.

Why This Pattern Is Awesome

This approach gives you several key benefits:

Centralized Logic: Avoid repeating feature-flag checks in every Razor view.
Performance Gains: Reduce logic in views and avoid processing unnecessary blocks.
Testability: Easily toggle features in tests by swapping the feature flags dictionary.
Flexibility: Inject any service or config into your initializer, including per-request logic.

TagHelpers are a powerful abstraction in ASP.NET Core, but they become even more useful when combined with ITagHelperInitializer<T>. Whether you’re injecting feature flags, version info, localization resources, or other shared data this pattern helps you keep views clean and logic centralized.

Try applying this in your next ASP.NET Core project you’ll be surprised how much cleaner and more maintainable your UI layer becomes.