3

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

Kristian Barrett
  • 3,574
  • 2
  • 26
  • 40
Magnus Gladh
  • 1,817
  • 4
  • 20
  • 31

2 Answers2

2

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}");
}
Magnus Gladh
  • 1,817
  • 4
  • 20
  • 31
1

You could use ServiceBusTriggerAttribute to achieve it.

First, use AddAzureAppConfiguration to get the endpoint, topic and subscriptname.

var builder = new ConfigurationBuilder();
builder.AddAzureAppConfiguration(Environment.GetEnvironmentVariable("ConnectionString"));
var config = builder.Build();
string message = config["TestApp:Settings:Message"];

Then use ServiceBusTriggerAttribute to takes the name of the topic and subscription to bind the attribute.

var attributes = new Attribute[]
{
    new ServiceBusAccountAttribute("yourservicebusname"),
    new ServiceBusTriggerAttribute(topic,sub)
};
var outputSbMessage = await binder.BindAsync<IAsyncCollector<BrokeredMessage>>(attributes);
Joey Cai
  • 18,968
  • 1
  • 20
  • 30
  • Hi.If I understand your code, you are getting the information from the azure configuration when you want to send a message to a queue from the functions. I want to get the information from where the messages should be extract in my function. Or have I missed something. – Magnus Gladh Jul 10 '19 at 11:35
  • So you do not get info from [app configuration](https://learn.microsoft.com/en-us/azure/azure-app-configuration/quickstart-azure-function-csharp#create-an-app-configuration-store)? And get info from local.setting.json? – Joey Cai Jul 11 '19 at 01:36