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()
{