Search code examples
azureazure-functionsazureservicebusazure-app-configuration

Is it possible to use AzureAppConfiguration together with an Azure Function ServiceBusTrigger


Today I have an Azure Function with the ServiceBusTrigger that reads values from my settings file. Like this:

[FunctionName("BookingEventListner")]
public static async Task Run([ServiceBusTrigger("%topic_name%", "%subscription_name%", Connection = "BookingservicesTopicEndpoint")]Microsoft.Azure.ServiceBus.Message mySbMsg, ILogger log)
{

But I am using Azure App Configuration with other projects in this solution and would like to store the endpoint, topic and subscriptname into the Azure App Configuration also (well adding them is not a problem but retrieving them are).

Is there someway to add the AzureAppConfiguration provider to the configuration handler, just that I can do in a web-app?

webHostBuilder.ConfigureAppConfiguration((context, config) =>
{
    var configuration = config.Build();
    config.AddAzureAppConfiguration(options =>
    {
        var azureConnectionString = configuration[TRS.Shared.AspNetCore.Constants.CONFIGURATION_KEY_AZURECONFIGURATION_CONNECTIONSTRING];

        if (string.IsNullOrWhiteSpace(azureConnectionString)
                || !azureConnectionString.StartsWith("Endpoint=https://"))
            throw new InvalidOperationException($"Missing/wrong configuration value for key '{Constants.CONFIGURATION_KEY_AZURECONFIGURATION_CONNECTIONSTRING}'.");

        options.Connect(azureConnectionString);
    });
});

Best Regards Magnus


Solution

  • I found a helpful link here: http://marcelegger.net/azure-functions-v2-keyvault-and-iconfiguration#more-45

    That helped me on the way, and this is how I do it. First I create an extensions method for the IWebJobsBuilder interface.

       /// <summary>
        /// Set up a connection to AzureAppConfiguration
        /// </summary>
        /// <param name="webHostBuilder"></param>
        /// <param name="azureAppConfigurationConnectionString"></param>
        /// <returns></returns>
        public static IWebJobsBuilder AddAzureConfiguration(this IWebJobsBuilder webJobsBuilder)
        {
            //-- Get current configuration
            var configBuilder = new ConfigurationBuilder();
            var descriptor = webJobsBuilder.Services.FirstOrDefault(d => d.ServiceType == typeof(IConfiguration));
            if (descriptor?.ImplementationInstance is IConfigurationRoot configuration)
                configBuilder.AddConfiguration(configuration);
    
            var config = configBuilder.Build();
    
            //-- Add Azure Configuration
            configBuilder.AddAzureAppConfiguration(options =>
            {
                var azureConnectionString = config[TRS.Shared.Constants.CONFIGURATION.KEY_AZURECONFIGURATION_CONNECTIONSTRING];
    
                if (string.IsNullOrWhiteSpace(azureConnectionString)
                        || !azureConnectionString.StartsWith("Endpoint=https://"))
                    throw new InvalidOperationException($"Missing/wrong configuration value for key '{TRS.Shared.Constants.CONFIGURATION.KEY_AZURECONFIGURATION_CONNECTIONSTRING}'.");
    
                options.Connect(azureConnectionString);
            });
            //build the config again so it has the key vault provider
            config = configBuilder.Build();
    
            //replace the existing config with the new one
            webJobsBuilder.Services.Replace(ServiceDescriptor.Singleton(typeof(IConfiguration), config));
            return webJobsBuilder;
        }
    

    Where the azureConnectionString is read from you appsetting.json and should contain the url to the Azure App Configuration.

    When that is done we need to create a "startup" class in the Azure Func project, that will look like this.

       public class Startup : IWebJobsStartup
        {
            //-- Constructor
            public Startup() { }
    
            //-- Methods
            public void Configure(IWebJobsBuilder builder)
            {
                //-- Adds a reference to our Azure App Configuration so we can store our variables there instead of in the local settings file.
                builder.AddAzureConfiguration(); 
                ConfigureServices(builder.Services)
                    .BuildServiceProvider(true);
            }
            private IServiceCollection ConfigureServices(IServiceCollection services)
            {
                services.AddLogging();
                return services;
            }
        }
    

    in my func class I can now extract the values from my Azure App Configuration exactly as if they where written in my appsetting.json file.

    [FunctionName("FUNCTION_NAME")]
    public async Task Run([ServiceBusTrigger("%KEYNAME_FOR_TOPIC%", "%KEYNAME_FOR_SUBSCRIPTION%", Connection = "KEY_NAME_FOR_SERVICEBUS_ENDPOINT")]Microsoft.Azure.ServiceBus.Message mySbMsg
        , ILogger log)
    {
        log.LogInformation($"C# ServiceBus topic trigger function processed message: {mySbMsg.MessageId}");
    }