4

We have FeatureFlag: IsServiceNeeded with no label set in Feature Manager of Azure App Configuration. We have used in built method AddAzureAppConfiguration by setting up the cache interval.

We are using .net core 3.1 web api and Feature Manager of Azure App Configuration.

We had IsServiceNeeded enabled during initialization of the app and after few hours, we disabled IsServiceNeed. We wait for entire day, but don't see the difference since the below returns true instead of false. We were expecting it to update every 3 minutes due to how we have it configured in program.cs file.

await _featureManager.IsEnabledAsync("IsServiceNeeded")

Let me know if you see anything odd with below. Thanks in advance,

Here is the code snippet we are using it.

Program.cs file

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((context, config) =>
            {
                var configurationRoot = config.Build();
                var appConfigConString = configurationRoot["AppConfigConnectionString"];

                config.AddAzureAppConfiguration(options => options.Connect(appConfigConString).UseFeatureFlags(featureFlagOptions => {
                    **featureFlagOptions.CacheExpirationInterval = TimeSpan.FromMinutes(3);**
                }));
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

Startup.cs file

public class Startup
{
    public IConfiguration Configuration { get; }
    public string ContentRootPath { get; set; }
    
    public Startup(IWebHostEnvironment env, IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddHsts(options =>
        {
            options.Preload = true;
            options.IncludeSubDomains = true;
            options.MaxAge = TimeSpan.FromDays(365);
        });

        var conf = Configuration.GetSection("AppSettings").Get<Config>();

        services.Configure<Config>(Configuration.GetSection("AppSettings"));

        services.AddSingleton<IAppSettings>(c => conf);**

        services.AddScoped<IProcessHandler, ProcessHandler>();
        **services.AddFeatureManagement();**
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseHsts();
        app.UseHttpsRedirection();
        app.UseHttpStatusCodeExceptionMiddleware();

        app.UseHttpsRedirection();

        app.UseRouting();

        app.UseAuthentication();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }

        private static void LoadMediatorHandlers(IServiceCollection services)
        {
            foreach (var assembly in Assembly
                                     .GetEntryAssembly()
                                     .GetReferencedAssemblies()
                                     .Select(Assembly.Load)
                                     .Where(name => (name.FullName.Contains("Queries") || name.FullName.Contains("Commands"))))
            {
                services.AddMediatR(assembly);
            }
            services.AddMediatR(typeof(Startup));
            services.AddScoped<IMediator, Mediator>();
        }   
    }

Application of Feature Flag:

public class ProcessHandler : IProcessHandler
{
    private readonly IFeatureManager _featureManager;

    public ProcessHandler(IFeatureManager featureManager)
    {
        _featureManager = featureManager;
    }

    public async Task<ClassA> ProcessXyz()
    {
        if (`await _featureManager.IsEnabledAsync("IsServiceNeeded")`)
        {
            return new ClassA();
        }
        
        return null;
    }   
}

Please Note: I have just added the required code and replaced actual names for security issues.

Thanks in advance

Vicky
  • 624
  • 2
  • 12
  • 35

1 Answers1

3

What is missing is the middleware that refreshes feature flags (and configuration) from Azure App Configuration.

Open your startup.cs, add below

public void ConfigureServices(IServiceCollection services)
{
    // ...
    services.AddAzureAppConfiguration();
    services.AddFeatureManagement();
}

And then add below

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // ...
    app.UseAzureAppConfiguration();
}
Zhenlan Wang
  • 1,213
  • 8
  • 10
  • We did try the above earlier but it did not work. What was required is IConfigurationRefresher interface and tryRefresh method to be invoked before using the flag. thank you! – Vicky Mar 14 '22 at 01:21
  • The App Configuration middleware will take care of obtaining the `IConfigurationRefresher` object and calling `TryRefresh` upon every incoming request to your application. Can you please check out the "Note" at the end of the section in this document to see what could be the cause of the issue? https://learn.microsoft.com/en-us/azure/azure-app-configuration/enable-dynamic-configuration-aspnet-core?tabs=core3x#reload-data-from-app-configuration – Zhenlan Wang Mar 15 '22 at 18:05