While custom feature filters solve the problem of isolating the feature to a specific group or individual it may not be appropriate to rely on the HttpContext for every application we build.
For example, a console app will not have ambient HttpContext to check if the user has a specific email address that matches the email declared in the feature flag section.
For this purpose, we have Contextual Feature Filters in Microsoft.FeatureManagement
package which take a context and evaluate the feature flag against a given context.
The contextual feature filters are declared and implemented similarly to custom feature filters.
Let’s see this in action.
IContextualFeatureFilter interface
public interface IContextualFeatureFilter<TContext> : Microsoft.FeatureManagement.IFeatureFilterMetadata
Contextual feature filters will only be executed if a context that is assignable from TContext
is available.
Declaring contextual feature filter
Let’s create a contextual feature filter by implementing IContextualFeatureFilter
interface.
public class AccountIdFilter : IContextualFeatureFilter<IAccountIdContext> { public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext featureFilterContext, IAccountIdContext appContext) { var settings = featureFilterContext.Parameters.Get<AccountIdSettings>(); return Task.FromResult(settings.AccountId == appContext.AccountId); } } public interface IAccountIdContext { string AccountId { get; set; } } public class AccountIdContext: IAccountIdContext { public string AccountId { get; set; } public AccountIdContext(string accountId) { AccountId = accountId; } } public class AccountIdSettings { public string AccountId { get; set; } }
Instead of injecting the HttpContextAccessor
to get the httpContext and get the account id or email to validate the feature flag, we get the AccountIdContext
passed to the EvaluateAsync
method.
We compare the app settings account id with the account id in the context. If they both match the feature flag is enabled, otherwise false.
Invoking IsEnabledAsync with context
Along with the feature flag name we also pass in the context to compare with.
if (await featureManager.IsEnabledAsync("SecretFeature", new AccountIdContext("123"))) { // do your something }
appsettings.json configuration
The appsettings.json file should be similar to how we configure custom feature filters.
"FeatureManagement": { "SecretFeature": { "EnabledFor": [ { "Name": "AccountId", "Parameters": { "AccountId": "d128f098-5a5b-4218-bb61-74305ecbdd32" } } ] } }
References
Contextual Feature Filters in Feature Management
Karthik is a passionate Full Stack developer working primarily on .NET Core, microservices, distributed systems, VUE and JavaScript. He also loves NBA basketball so you might find some NBA examples in his posts and he owns this blog.
Pingback: Dew Drop – November 7, 2022 (#3802) – Morning Dew by Alvin Ashcraft