Skip to main content

Configuration

Learn about configuration options and advanced settings for the .NET SDK.

Disabled Action Handling​

When an MVC controller or action is blocked because none of the features it specifies are enabled, a registered IDisabledFeaturesHandler will be invoked. By default, a minimalistic handler is registered which returns HTTP 404. This can be overridden using the IFeatureManagementBuilder when registering feature flags.

public interface IDisabledFeaturesHandler
{
Task HandleDisabledFeature(IEnumerable<string> features, ActionExecutingContext context);
}

Example implementation​

public class FeatureNotEnabledHandler : IDisabledFeaturesHandler
{
public Task HandleDisabledFeatures(IEnumerable<string> features, ActionExecutingContext context)
{
var result = new ViewResult()
{
ViewName = "Views/Shared/FeatureNotEnabled.cshtml",
ViewData = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary())
};

result.ViewData["FeatureName"] = string.Join(", ", features);

context.Result = result;

return Task.CompletedTask;
}
}

Then register as singleton in startup.cs

services.AddSingleton<IDisabledFeaturesHandler, FeatureNotEnabledHandler>();

Undefined Features In Development​

To enable a more streamlined developer experience, we can treat undefined features as Always On, to avoid having to go into Toggly and define the feature.

Simply add UndefinedEnabledOnDevelopment to AddTogglyWeb.

builder.Services.AddTogglyWeb(options =>
{
options.AppKey = builder.Configuration["Toggly:AppKey"]!;
options.Environment = builder.Configuration["Toggly:Environment"]!;
options.UndefinedEnabledOnDevelopment = true;
});
success

Don't worry, we auto-detect new flags being checked, and show you any undefined ones on the Feature Definitions page at the bottom.

info

This works with app.Environment.IsDevelopment() to only affect development. For all other environments, you'll still need to define the feature

Deployments and Version​

info

We try to detect when you've released a new version of your app using the AppVersion option specified in AddTogglyWeb. If not specified, we try to use the version of the entry assembly to your app

To specify a version manually, add the current version to AddTogglyWeb

services.AddTogglyWeb(options =>
{
options.AppKey = Configuration["Toggly:AppKey"]!;
options.Environment = Configuration["Toggly:Environment"]!;
options.AppVersion = "7.10.1";
});

If not specified, we default to Assembly.GetEntryAssembly()?.GetName().Version

To disable version tracking, set AppVersion to String.Empty

When feature flags gate security-sensitive behavior, enable cryptographic verification:

builder.Services.AddTogglyWeb(options =>
{
options.AppKey = builder.Configuration["Toggly:AppKey"]!;
options.Environment = builder.Configuration["Toggly:Environment"]!;
options.UseSignedDefinitions = true;
options.AllowedKeyIds = new HashSet<string> { "yourKeyIdES256" }; // optional pin
// options.JwksCacheDuration = TimeSpan.FromDays(30); // default
});

BaseUrl and DefinitionsBaseUrl are trusted configuration. Only override them for self-hosted or private deployments you control. A malicious DefinitionsBaseUrl can redirect definitions/JWKS fetches.

Hangfire jobs registered via AddOrUpdateJob follow flag state — pair them with UseSignedDefinitions in production so job enablement cannot be flipped by an unsigned definitions channel.

Missing Feature Filters​

By default the SDK fails closed: evaluating a flag that references an unregistered filter throws. To ignore missing filters (not recommended for security-sensitive apps):

services.Configure<FeatureManagementOptions>(options =>
{
options.IgnoreMissingFeatureFilters = true;
});

Logging​

Set the Toggly.FeatureManagement category to Debug when diagnosing fetch or signature issues. Remote HTTP response bodies are logged only at Debug:

builder.Logging.AddFilter("Toggly.FeatureManagement", LogLevel.Debug);

Debugging Endpoint​

In case you want to see the current definitions of the flags or recorded metrics, usage stats, you can use the IMetricsDebug, IUsageStatsDebug or IFeatureProviderDebug. App keys in debug payloads are masked (last 6 characters only).

app.MapGet("/feature-debug", async ctx => await ctx.Response.WriteAsJsonAsync(new
{
Metrics = ctx.RequestServices.GetRequiredService<IMetricsDebug>().GetDebugInfo(),
UsageStats = ctx.RequestServices.GetRequiredService<IUsageStatsDebug>().GetDebugInfo(),
FeatureProvider = ctx.RequestServices.GetRequiredService<IFeatureProviderDebug>().GetDebugInfo(),
}));