diff --git a/src/Microsoft.FeatureManagement/FeatureManagementError.cs b/src/Microsoft.FeatureManagement/FeatureManagementError.cs index a1e3319f..1cdb9eed 100644 --- a/src/Microsoft.FeatureManagement/FeatureManagementError.cs +++ b/src/Microsoft.FeatureManagement/FeatureManagementError.cs @@ -16,6 +16,11 @@ public enum FeatureManagementError /// /// A feature filter configured for the feature being evaluated is an ambiguous reference to multiple registered feature filters. /// - AmbiguousFeatureFilter + AmbiguousFeatureFilter, + + /// + /// A feature that was requested for evaluation was not found. + /// + MissingFeature } } diff --git a/src/Microsoft.FeatureManagement/FeatureManagementOptions.cs b/src/Microsoft.FeatureManagement/FeatureManagementOptions.cs index 9322934e..e425c054 100644 --- a/src/Microsoft.FeatureManagement/FeatureManagementOptions.cs +++ b/src/Microsoft.FeatureManagement/FeatureManagementOptions.cs @@ -11,7 +11,15 @@ public class FeatureManagementOptions /// /// Controls the behavior of feature evaluation when dependent feature filters are missing. /// If missing feature filters are not ignored an exception will be thrown when attempting to evaluate a feature that depends on a missing feature filter. + /// The default value is false. /// public bool IgnoreMissingFeatureFilters { get; set; } + + /// + /// Controls the behavior of feature evaluation when the target feature is missing. + /// If missing features are not ignored an exception will be thrown when attempting to evaluate them. + /// The default value is true. + /// + public bool IgnoreMissingFeatures { get; set; } = true; } } diff --git a/src/Microsoft.FeatureManagement/FeatureManager.cs b/src/Microsoft.FeatureManagement/FeatureManager.cs index 25873f50..74bd10ab 100644 --- a/src/Microsoft.FeatureManagement/FeatureManager.cs +++ b/src/Microsoft.FeatureManagement/FeatureManager.cs @@ -141,6 +141,19 @@ private async Task IsEnabledAsync(string feature, TContext appCo } } } + else + { + string errorMessage = $"The feature declaration for the feature '{feature}' was not found."; + + if (!_options.IgnoreMissingFeatures) + { + throw new FeatureManagementException(FeatureManagementError.MissingFeatureFilter, errorMessage); + } + else + { + _logger.LogWarning(errorMessage); + } + } foreach (ISessionManager sessionManager in _sessionManagers) { diff --git a/tests/Tests.FeatureManagement/FeatureManagement.cs b/tests/Tests.FeatureManagement/FeatureManagement.cs index e30888e4..d7e85366 100644 --- a/tests/Tests.FeatureManagement/FeatureManagement.cs +++ b/tests/Tests.FeatureManagement/FeatureManagement.cs @@ -485,6 +485,31 @@ public async Task SwallowsExceptionForMissingFeatureFilter() Assert.False(isEnabled); } + [Fact] + public async Task ThrowsForMissingFeatures() + { + IConfiguration config = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build(); + + var services = new ServiceCollection(); + + services + .Configure(options => + { + options.IgnoreMissingFeatures = false; + }); + + services + .AddSingleton(config) + .AddFeatureManagement(); + + ServiceProvider serviceProvider = services.BuildServiceProvider(); + + IFeatureManager featureManager = serviceProvider.GetRequiredService(); + + FeatureManagementException fme = await Assert.ThrowsAsync(() => + featureManager.IsEnabledAsync("NonExistentFeature")); + } + [Fact] public async Task CustomFeatureDefinitionProvider() {