diff --git a/src/Microsoft.FeatureManagement/FeatureFilterEvaluationContext.cs b/src/Microsoft.FeatureManagement/FeatureFilterEvaluationContext.cs
index ccc7a884..0ea5f730 100644
--- a/src/Microsoft.FeatureManagement/FeatureFilterEvaluationContext.cs
+++ b/src/Microsoft.FeatureManagement/FeatureFilterEvaluationContext.cs
@@ -22,13 +22,12 @@ public class FeatureFilterEvaluationContext
public IConfiguration Parameters { get; set; }
///
- /// The settings provided for the feature filter to use when evaluating whether the feature should be enabled. This property takes precedence over and if both are provided.
- ///
- public object ParametersObject { get; set; }
-
- ///
- /// A settings object, if any, that has been pre-bound from .
- /// The settings are made available for s that implement .
+ /// A settings object, if any, provided for the feature filter to use when evaluating whether the feature should be enabled.
+ /// This property is populated in two cases:
+ ///
+ /// - For features that provide parameters as an object, via .
+ /// - For s that implement .
+ ///
///
public object Settings { get; set; }
diff --git a/src/Microsoft.FeatureManagement/FeatureFilters/PercentageFilter.cs b/src/Microsoft.FeatureManagement/FeatureFilters/PercentageFilter.cs
index 044215f8..91bf6c44 100644
--- a/src/Microsoft.FeatureManagement/FeatureFilters/PercentageFilter.cs
+++ b/src/Microsoft.FeatureManagement/FeatureFilters/PercentageFilter.cs
@@ -49,18 +49,16 @@ public Task EvaluateAsync(FeatureFilterEvaluationContext context)
throw new ArgumentNullException(nameof(context));
}
- //
- // Check if ParametersObject available (takes precedence), then prebound settings, otherwise bind from parameters.
- PercentageFilterSettings settings;
-
- if (context.ParametersObject != null && !(context.ParametersObject is PercentageFilterSettings))
+ if (context.Settings != null && !(context.Settings is PercentageFilterSettings))
{
throw new ArgumentException(
- $"The '{Alias}' feature filter for feature '{context.FeatureName}' has a {nameof(context.ParametersObject)} of type '{context.ParametersObject.GetType()}', but expected '{typeof(PercentageFilterSettings)}'.",
- nameof(context.ParametersObject));
+ $"The '{Alias}' feature filter for feature '{context.FeatureName}' has a {nameof(context.Settings)} value of type '{context.Settings.GetType()}', but expected '{typeof(PercentageFilterSettings)}'.",
+ nameof(context.Settings));
}
- settings = (PercentageFilterSettings)context.ParametersObject ?? (PercentageFilterSettings)context.Settings ?? (PercentageFilterSettings)BindParameters(context.Parameters);
+ //
+ // Check if prebound settings available, otherwise bind from parameters.
+ PercentageFilterSettings settings = (PercentageFilterSettings)context.Settings ?? (PercentageFilterSettings)BindParameters(context.Parameters);
bool result = true;
diff --git a/src/Microsoft.FeatureManagement/FeatureFilters/TimeWindowFilter.cs b/src/Microsoft.FeatureManagement/FeatureFilters/TimeWindowFilter.cs
index 608e8a1a..68cd3285 100644
--- a/src/Microsoft.FeatureManagement/FeatureFilters/TimeWindowFilter.cs
+++ b/src/Microsoft.FeatureManagement/FeatureFilters/TimeWindowFilter.cs
@@ -70,18 +70,16 @@ public Task EvaluateAsync(FeatureFilterEvaluationContext context)
throw new ArgumentNullException(nameof(context));
}
- //
- // Check if ParametersObject available (takes precedence), then prebound settings, otherwise bind from parameters.
- TimeWindowFilterSettings settings;
-
- if (context.ParametersObject != null && !(context.ParametersObject is TimeWindowFilterSettings))
+ if (context.Settings != null && !(context.Settings is TimeWindowFilterSettings))
{
throw new ArgumentException(
- $"The '{Alias}' feature filter for feature '{context.FeatureName}' has a {nameof(context.ParametersObject)} of type '{context.ParametersObject.GetType()}', but expected '{typeof(TimeWindowFilterSettings)}'.",
- nameof(context.ParametersObject));
+ $"The '{Alias}' feature filter for feature '{context.FeatureName}' has a {nameof(context.Settings)} value of type '{context.Settings.GetType()}', but expected '{typeof(TimeWindowFilterSettings)}'.",
+ nameof(context.Settings));
}
- settings = (TimeWindowFilterSettings)context.ParametersObject ?? (TimeWindowFilterSettings)context.Settings ?? (TimeWindowFilterSettings)BindParameters(context.Parameters);
+ //
+ // Check if prebound settings available, otherwise bind from parameters.
+ TimeWindowFilterSettings settings = (TimeWindowFilterSettings)context.Settings ?? (TimeWindowFilterSettings)BindParameters(context.Parameters);
DateTimeOffset now = SystemClock?.GetUtcNow() ?? DateTimeOffset.UtcNow;
diff --git a/src/Microsoft.FeatureManagement/FeatureManager.cs b/src/Microsoft.FeatureManagement/FeatureManager.cs
index c8c8eaa8..c35df318 100644
--- a/src/Microsoft.FeatureManagement/FeatureManager.cs
+++ b/src/Microsoft.FeatureManagement/FeatureManager.cs
@@ -498,11 +498,14 @@ private async ValueTask IsEnabledAsync(FeatureDefinition feature
{
FeatureName = featureDefinition.Name,
Parameters = featureFilterConfiguration.Parameters,
- ParametersObject = featureFilterConfiguration.ParametersObject,
+ Settings = featureFilterConfiguration.ParametersObject,
CancellationToken = cancellationToken
};
- BindSettings(filter, context, filterIndex);
+ if (context.Settings == null)
+ {
+ BindSettings(filter, context, filterIndex);
+ }
//
// IContextualFeatureFilter
diff --git a/src/Microsoft.FeatureManagement/Targeting/ContextualTargetingFilter.cs b/src/Microsoft.FeatureManagement/Targeting/ContextualTargetingFilter.cs
index 014aa2af..bc592a3f 100644
--- a/src/Microsoft.FeatureManagement/Targeting/ContextualTargetingFilter.cs
+++ b/src/Microsoft.FeatureManagement/Targeting/ContextualTargetingFilter.cs
@@ -67,18 +67,16 @@ public Task EvaluateAsync(FeatureFilterEvaluationContext context, ITargeti
throw new ArgumentNullException(nameof(targetingContext));
}
- //
- // Check if ParametersObject available (takes precedence), then prebound settings, otherwise bind from parameters.
- TargetingFilterSettings settings;
-
- if (context.ParametersObject != null && !(context.ParametersObject is TargetingFilterSettings))
+ if (context.Settings != null && !(context.Settings is TargetingFilterSettings))
{
throw new ArgumentException(
- $"The '{Alias}' feature filter for feature '{context.FeatureName}' has a {nameof(context.ParametersObject)} of type '{context.ParametersObject.GetType()}', but expected '{typeof(TargetingFilterSettings)}'.",
- nameof(context.ParametersObject));
+ $"The '{Alias}' feature filter for feature '{context.FeatureName}' has a {nameof(context.Settings)} value of type '{context.Settings.GetType()}', but expected '{typeof(TargetingFilterSettings)}'.",
+ nameof(context.Settings));
}
- settings = (TargetingFilterSettings)context.ParametersObject ?? (TargetingFilterSettings)context.Settings ?? (TargetingFilterSettings)BindParameters(context.Parameters);
+ //
+ // Check if prebound settings available, otherwise bind from parameters.
+ TargetingFilterSettings settings = (TargetingFilterSettings)context.Settings ?? (TargetingFilterSettings)BindParameters(context.Parameters);
return Task.FromResult(TargetingEvaluator.IsTargeted(targetingContext, settings, _options.IgnoreCase, context.FeatureName));
}
diff --git a/tests/Tests.FeatureManagement/FeatureManagementTest.cs b/tests/Tests.FeatureManagement/FeatureManagementTest.cs
index d38d7b5d..b307d892 100644
--- a/tests/Tests.FeatureManagement/FeatureManagementTest.cs
+++ b/tests/Tests.FeatureManagement/FeatureManagementTest.cs
@@ -1094,9 +1094,9 @@ public async Task UsesParametersObject()
testFeatureFilter.Callback = (evaluationContext) =>
{
//
- // When ParametersObject is set, it should be available on the context
- // so custom filters can use it with their own precedence logic.
- Assert.Same(parameterObject, evaluationContext.ParametersObject);
+ // When ParametersObject is set, it should be available on the context via settings
+ // so custom filters can use it.
+ Assert.Same(parameterObject, evaluationContext.Settings);
return Task.FromResult(true);
};
@@ -1157,7 +1157,6 @@ public async Task ParametersObjectFallsBackToParametersWhenNull()
//
// When ParametersObject is null, Settings should be populated
// by IFilterParametersBinder as usual.
- Assert.Null(evaluationContext.ParametersObject);
Assert.NotNull(evaluationContext.Settings);
return Task.FromResult(true);