Quickstart: Add feature flags to a .NET background service

In this quickstart, you incorporate the feature management capability from Azure App Configuration into a .NET background service. You use App Configuration to centrally store and manage your feature flags.

Prerequisites

Feature management support extends the dynamic configuration feature in App Configuration. The example in this quickstart builds on the .NET background service app introduced in the dynamic configuration tutorial. Before you continue, finish the following tutorial to create a .NET background service app with dynamic configuration first.

Add a feature flag

Add a feature flag called Beta to the App Configuration store and leave Label and Description with their default values. For more information about how to add feature flags to a store using the Azure portal or the CLI, go to Create a feature flag.

Screenshot showing fields to enable a feature flag named Beta.

Use the feature flag

  1. Add references to the Microsoft.FeatureManagement NuGet package by running the following command:

    dotnet add package Microsoft.FeatureManagement
    
  2. Run the following command to restore packages for your project:

    dotnet restore
    
  3. Open Program.cs and add the following statement:

    using Microsoft.FeatureManagement;
    
  4. Add a call to the UseFeatureFlags method inside the AddAzureAppConfiguration call and register feature management services.

    // Existing code in Program.cs
    // ... ...
    
    builder.Configuration.AddAzureAppConfiguration(options =>
    {
        options.Connect(Environment.GetEnvironmentVariable("ConnectionString"));
    
        // Use feature flags
        options.UseFeatureFlags();
    
        // Register the refresher so that the Worker service can consume it through dependency injection
        builder.Services.AddSingleton(options.GetRefresher());
    });
    
    // Register feature management services
    builder.Services.AddFeatureManagement();
    
    // The rest of existing code in Program.cs
    // ... ...
    

    Tip

    When no parameter is passed to the UseFeatureFlags method, it loads all feature flags with no label in your App Configuration store. The default refresh interval of feature flags is 30 seconds. You can customize this behavior via the FeatureFlagOptions parameter. For example, the following code snippet loads only feature flags that start with TestApp: in their key name and have the label dev. The code also changes the refresh interval time to 5 minutes. Note that this refresh interval time is separate from that for regular key-values.

    options.UseFeatureFlags(featureFlagOptions =>
    {
        featureFlagOptions.Select("TestApp:*", "dev");
        featureFlagOptions.CacheExpirationInterval = TimeSpan.FromMinutes(5);
    });
    
  5. Open Worker.cs and add the following statement:

    using Microsoft.FeatureManagement;
    
  6. Update the constructor of the Worker service to obtain instances of IConfigurationRefresher and IFeatureManager through dependency injection.

    public class Worker : BackgroundService
    {
        private readonly ILogger<Worker> _logger;
        private readonly IConfigurationRefresher _refresher;
        private readonly IFeatureManager _featureManager;
    
        public Worker(ILogger<Worker> logger, IConfigurationRefresher refresher, IFeatureManager featureManager)
        {
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
            _refresher = refresher ?? throw new ArgumentNullException(nameof(refresher));
            _featureManager = featureManager ?? throw new ArgumentNullException(nameof(featureManager));
        }
    
        // ... ...
    }
    
  7. Update the ExecuteAsync method to log a message depending on the state of the feature flag.

    The TryRefreshAsync method is called at the beginning of every iteration of the task execution to refresh the feature flag. It will be a no-op if the refresh interval time window isn't reached. The await operator is not used so that the feature flags are refreshed without blocking the current iteration of the task execution. In that case, later iterations of the task execution will get updated value.

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            // Intentionally not await TryRefreshAsync to avoid blocking the execution.
            _refresher.TryRefreshAsync(stoppingToken);
    
            if (_logger.IsEnabled(LogLevel.Information))
            {
                if (await _featureManager.IsEnabledAsync("Beta"))
                {
                    _logger.LogInformation("[{time}]: Worker is running with Beta feature.", DateTimeOffset.Now);
                }
                else
                {
                    _logger.LogInformation("[{time}]: Worker is running.", DateTimeOffset.Now);
                }
            }
    
            await Task.Delay(TimeSpan.FromSeconds(30), stoppingToken);
        }
    }
    

Build and run the app locally

  1. Run the following command to build the app:

    dotnet build
    
  2. After the build successfully completes, run the following command to run the app locally:

    dotnet run
    
  3. You should see the following outputs in the console.

    Screenshot of the console with background service running with feature flag disabled.

  4. Sign in to the Azure portal. Select All resources, and select the App Configuration store that you created previously.

  5. Select Feature manager and locate the Beta feature flag. Enable the flag by selecting the checkbox under Enabled.

  6. Wait a few moments for the refresh interval time window to pass. You will see the updated log message.

    Screenshot of the console with background service running with feature flag enabled.

Clean up resources

If you don't want to continue using the resources created in this article, delete the resource group you created here to avoid charges.

Important

Deleting a resource group is irreversible. The resource group and all the resources in it are permanently deleted. Ensure that you don't accidentally delete the wrong resource group or resources. If you created the resources for this article inside a resource group that contains other resources you want to keep, delete each resource individually from its respective pane instead of deleting the resource group.

  1. Sign in to the Azure portal, and select Resource groups.
  2. In the Filter by name box, enter the name of your resource group.
  3. In the result list, select the resource group name to see an overview.
  4. Select Delete resource group.
  5. You're asked to confirm the deletion of the resource group. Enter the name of your resource group to confirm, and select Delete.

After a few moments, the resource group and all its resources are deleted.

Next steps

To enable feature management capability for other types of apps, continue to the following tutorials.

To learn more about managing feature flags in Azure App Configuration, continue to the following tutorial.