Skip to content

Files

Latest commit

 

History

History
243 lines (180 loc) · 11.5 KB

enable-dynamic-configuration-azure-functions-csharp.md

File metadata and controls

243 lines (180 loc) · 11.5 KB
title description services author manager ms.service ms.devlang ms.topic ms.date ms.author ms.custom ms.tgt_pltfrm
Tutorial for using Azure App Configuration dynamic configuration in an Azure Functions app
In this tutorial, you learn how to dynamically update the configuration data for Azure Functions apps
azure-app-configuration
zhenlan
qingye
azure-app-configuration
csharp
tutorial
09/14/2022
zhenlwa
devx-track-csharp, azure-functions
Azure Functions

Tutorial: Use dynamic configuration in an Azure Functions app

The App Configuration .NET configuration provider supports caching and refreshing configuration dynamically driven by application activity. This tutorial shows how you can implement dynamic configuration updates in your code. It builds on the Azure Functions app introduced in the quickstarts. Before you continue, finish Create an Azure functions app with Azure App Configuration first.

In this tutorial, you learn how to:

[!div class="checklist"]

  • Set up your Azure Functions app to update its configuration in response to changes in an App Configuration store.
  • Inject the latest configuration to your Azure Functions calls.

Prerequisites

Reload data from App Configuration

Azure Functions support running in-process or isolated-process. The main difference in App Configuration usage between the two modes is how the configuration is refreshed. In the in-process mode, you must make a call in each function to refresh the configuration. In the isolated-process mode, there is support for middleware. The App Configuration middleware, Microsoft.Azure.AppConfiguration.Functions.Worker, enables the call to refresh configuration automatically before each function is executed.

  1. Update the code that connects to App Configuration and add the data refreshing conditions.

    Open Startup.cs, and update the ConfigureAppConfiguration method.

    public override void ConfigureAppConfiguration(IFunctionsConfigurationBuilder builder)
    {
        builder.ConfigurationBuilder.AddAzureAppConfiguration(options =>
        {
            options.Connect(Environment.GetEnvironmentVariable("ConnectionString"))
                    // Load all keys that start with `TestApp:` and have no label
                    .Select("TestApp:*")
                    // Configure to reload configuration if the registered sentinel key is modified
                    .ConfigureRefresh(refreshOptions =>
                        refreshOptions.Register("TestApp:Settings:Sentinel", refreshAll: true));
        });
    }

    Open Program.cs, and update the Main method.

    public static void Main()
    {
        var host = new HostBuilder()
            .ConfigureAppConfiguration(builder =>
            {
                builder.AddAzureAppConfiguration(options =>
                {
                    options.Connect(Environment.GetEnvironmentVariable("ConnectionString"))
                            // Load all keys that start with `TestApp:` and have no label
                            .Select("TestApp:*")
                            // Configure to reload configuration if the registered sentinel key is modified
                            .ConfigureRefresh(refreshOptions =>
                                refreshOptions.Register("TestApp:Settings:Sentinel", refreshAll: true));
                });
            })
            .ConfigureFunctionsWorkerDefaults()
            .Build();
    
        host.Run();
    }

    The ConfigureRefresh method registers a setting to be checked for changes whenever a refresh is triggered within the application. The refreshAll parameter instructs the App Configuration provider to reload the entire configuration whenever a change is detected in the registered setting.

    All settings registered for refresh have a default cache expiration of 30 seconds before a new refresh is attempted. It can be updated by calling the AzureAppConfigurationRefreshOptions.SetCacheExpiration method.

    [!TIP] When you are updating multiple key-values in App Configuration, you normally don't want your application to reload configuration before all changes are made. You can register a sentinel key and update it only when all other configuration changes are completed. This helps to ensure the consistency of configuration in your application.

    You may also do the following to minimize the risk of inconsistencies:

    • Design your application to be tolerable for transient configuration inconsistency
    • Warm-up your application before bringing it online (serving requests)
    • Carry default configuration in your application and use it when configuration validation fails
    • Choose a configuration update strategy that minimizes the impact to your application, for example, a low traffic timing.
  1. Update the Configure method to make Azure App Configuration services available through dependency injection.

    public override void Configure(IFunctionsHostBuilder builder)
    {
        builder.Services.AddAzureAppConfiguration();
    }
  2. Open Function1.cs, and add the following namespaces.

    using System.Linq;
    using Microsoft.Extensions.Configuration.AzureAppConfiguration;

    Update the constructor to obtain the instance of IConfigurationRefresherProvider through dependency injection, from which you can obtain the instance of IConfigurationRefresher.

    private readonly IConfiguration _configuration;
    private readonly IConfigurationRefresher _configurationRefresher;
    
    public Function1(IConfiguration configuration, IConfigurationRefresherProvider refresherProvider)
    {
        _configuration = configuration;
        _configurationRefresher = refresherProvider.Refreshers.First();
    }
  3. Update the Run method and signal to refresh the configuration using the TryRefreshAsync method at the beginning of the Functions call. It will be a no-op if the cache expiration time window isn't reached. Remove the await operator if you prefer the configuration to be refreshed without blocking the current Functions call. In that case, later Functions calls will get updated value.

    public async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req, ILogger log)
    {
        log.LogInformation("C# HTTP trigger function processed a request.");
    
        await _configurationRefresher.TryRefreshAsync(); 
    
        string keyName = "TestApp:Settings:Message";
        string message = _configuration[keyName];
            
        return message != null
            ? (ActionResult)new OkObjectResult(message)
            : new BadRequestObjectResult($"Please create a key-value with the key '{keyName}' in App Configuration.");
    }
  1. Add a ConfigureServices call to the HostBuilder to make Azure App Configuration services available through dependency injection. Then update the ConfigureFunctionsWorkerDefaults to use App Configuration middleware for configuration data refresh.

    public static void Main()
    {
        var host = new HostBuilder()
            .ConfigureAppConfiguration(builder =>
            {
                // Omitted the code added in the previous step.
                // ... ...
            })
            .ConfigureServices(services =>
            {
                // Make Azure App Configuration services available through dependency injection.
                services.AddAzureAppConfiguration();
            })
            .ConfigureFunctionsWorkerDefaults(app =>
            {
                // Use Azure App Configuration middleware for data refresh.
                app.UseAzureAppConfiguration();
            })
            .Build();
    
        host.Run();
    }

Test the function locally

  1. Set an environment variable named ConnectionString, and set it to the access key to your app configuration store. If you use the Windows command prompt, run the following command and restart the command prompt to allow the change to take effect:

    setx ConnectionString "connection-string-of-your-app-configuration-store"

    If you use Windows PowerShell, run the following command:

    $Env:ConnectionString = "connection-string-of-your-app-configuration-store"

    If you use macOS or Linux, run the following command:

    export ConnectionString='connection-string-of-your-app-configuration-store'
  2. To test your function, press F5. If prompted, accept the request from Visual Studio to download and install Azure Functions Core (CLI) tools. You might also need to enable a firewall exception so that the tools can handle HTTP requests.

  3. Copy the URL of your function from the Azure Functions runtime output.

    Quickstart Function debugging in VS

  4. Paste the URL for the HTTP request into your browser's address bar. The following image shows the response in the browser to the local GET request returned by the function.

    Quickstart Function launch local

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

  6. Select Configuration explorer, and update the value of the following key:

    Key Value
    TestApp:Settings:Message Data from Azure App Configuration - Updated

    Then create the sentinel key or modify its value if it already exists, for example,

    Key Value
    TestApp:Settings:Sentinel v1
  7. Refresh the browser a few times. When the cached setting expires after 30 seconds, the page shows the response of the Functions call with updated value.

    Quickstart Function refresh local

Note

The example code used in this tutorial can be downloaded from App Configuration GitHub repo.

Clean up resources

[!INCLUDE azure-app-configuration-cleanup]

Next steps

In this tutorial, you enabled your Azure Functions app to dynamically refresh configuration settings from App Configuration. To learn how to use an Azure managed identity to streamline the access to App Configuration, continue to the next tutorial.

[!div class="nextstepaction"] Access App Configuration using managed identity