| name | toggle-global-features |
| description | ABP Global Features toggled before startup to include/remove whole module capabilities. USE FOR: GlobalFeatureManager, GlobalFeature/GlobalModuleFeatures, GlobalFeatureConfigurator, [RequiresGlobalFeature], startup-time controller/page/database-model gating. DO NOT USE FOR: tenant/edition feature values or [RequiresFeature] (manage-settings-and-features); user/role permissions (permissions-and-authorization); runtime configuration flags (read-configuration). |
| license | MIT |
Toggling Global Features in ABP
When to Use
- Let an application opt into an optional capability of a reusable module.
- Hide controllers/pages from API Explorer / remote-service discovery (and return 404 at runtime) when a capability is disabled.
- Exclude database model pieces before migrations/model creation, when a module configures its model conditionally on the feature state.
- Group module-wide switches behind a discoverable
GlobalModuleFeatures API.
When Not to Use
- Per-tenant or per-edition capabilities — use manage-settings-and-features.
- User/role access control — use permissions-and-authorization.
- A flag that changes while the application is running — use configuration/settings or another runtime mechanism.
How it works
Global Features are development/startup-time switches. They are disabled unless explicitly enabled. Configure them before application startup: a disabled controller/page/service stays in the application model but is hidden from API Explorer / remote-service discovery (ApiExplorer.IsVisible = false) and returns 404 at runtime, and a module can omit disabled database tables from its model. Neither behavior is re-evaluated after startup.
Define a named feature type:
[GlobalFeatureName("Shopping.Payment")]
public class PaymentFeature
{
}
Enable, disable, and inspect it through the process-wide singleton:
GlobalFeatureManager.Instance.Enable<PaymentFeature>();
GlobalFeatureManager.Instance.Disable("Shopping.Payment");
var enabled = GlobalFeatureManager.Instance.IsEnabled<PaymentFeature>();
Verified manager operations accept a generic feature type, Type, or string name. GetEnabledFeatureNames() returns the current enabled-name set as IEnumerable<string>.
Configure once before startup
The startup template generates an application-specific class such as MyProjectNameGlobalFeatureConfigurator. This is a template convention, not a framework type named GlobalFeatureConfigurator. It wraps changes in OneTimeRunner and is called from the Domain.Shared module's PreConfigureServices:
public static class MyAppGlobalFeatureConfigurator
{
private static readonly OneTimeRunner OneTimeRunner = new();
public static void Configure()
{
OneTimeRunner.Run(() =>
{
GlobalFeatureManager.Instance.Enable<PaymentFeature>();
});
}
}
public override void PreConfigureServices(ServiceConfigurationContext context)
{
MyAppGlobalFeatureConfigurator.Configure();
}
Guard a class
RequiresGlobalFeatureAttribute targets classes and accepts either a feature Type or a feature name:
[RequiresGlobalFeature(typeof(PaymentFeature))]
public class PaymentController : AbpController
{
}
For MVC controllers/pages, a disabled global-feature component stays in the application model but the service convention sets its ApiExplorer.IsVisible = false (hidden from API Explorer and remote-service discovery), and GlobalFeatureActionFilter/GlobalFeaturePageFilter return a NotFoundResult (404) for requests at runtime. For intercepted services implementing IGlobalFeatureCheckingEnabled, the global-feature interceptor throws AbpGlobalFeatureNotEnabledException. The attribute does not target individual methods.
Group a module's features
For a reusable module, derive each switch from GlobalFeature, derive a group from GlobalModuleFeatures, call AddFeature(...) in the group constructor, and expose an extension on GlobalModuleFeaturesDictionary. The group supports Enable<TFeature>(), Disable<TFeature>(), SetEnabled<TFeature>(bool), string-name equivalents, EnableAll(), and DisableAll().
GlobalFeatureManager.Instance.Modules.Ecommerce().Subscription.Enable();
GlobalFeatureManager.Instance.Modules.Ecommerce().EnableAll();
Use this grouping only when authoring a reusable module API; application code enabling existing module features should use the module's supplied extension.
Validation
- Start once with the feature disabled and verify the guarded controller/page returns
404 and is absent from the API Explorer / remote-service metadata.
- Enable it in
PreConfigureServices, restart, and verify the component is reachable and any model configuration the module gates on the feature is present.
- Verify
IsEnabled<TFeature>() and GetEnabledFeatureNames() reflect the startup configuration.
- For grouped features, verify
EnableAll() enables every feature added to AllFeatures.
- Generate or apply migrations only after the intended global-feature set is configured.
Common Pitfalls
- Changing a Global Feature at runtime — application models and database models may already be built; configure before startup and restart.
- Confusing it with tenant features — Global Features are process-wide startup switches, not tenant/edition values.
- Assuming
GlobalFeatureConfigurator is a framework API — it is an application-specific class generated by templates.
- Forgetting that features default to disabled — explicitly enable required module capabilities.
- Putting
[RequiresGlobalFeature] on a method — the attribute targets classes only.
- Creating migrations under the wrong switch set — database schema output can depend on enabled Global Features.
- Expecting
GlobalFeatureManager to trim the database model automatically — it does not. A module must check GlobalFeatureManager.Instance.IsEnabled<TFeature>() inside its own OnModelCreating/model-configuration code to include or omit tables (e.g. CmsKit's ConfigureCmsKit).