Skip to content

Contextual Feature Filters in ASP.NET Core

contextual feature filters

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

Leave a Reply

Your email address will not be published.