How to Initialize TagHelpers in ASP.NET Core with Shared Data
By Tan Lee Published on Apr 16, 2025 47
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.
- Boost Your ASP.NET Core Website Performance with .NET Profiler
- The name 'Session' does not exist in the current context
- Implementing Two-Factor Authentication with Google Authenticator in ASP.NET Core
- How to securely reverse-proxy ASP.NET Core
- How to Retrieve Client IP in ASP.NET Core Behind a Reverse Proxy
- Only one parameter per action may be bound from body in ASP.NET Core
- The request matched multiple endpoints in ASP.NET Core
- How to Create a custom model validation attribute in ASP.NET Core