Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to inject or use IConfiguration in Azure Function V3 with Dependency Injection when configuring a service

Normally in a .NET Core project I would create a 'boostrap' class to configure my service along with the DI registration commands. This is usually an extension method of IServiceCollection where I can call a method like .AddCosmosDbService and everything necessary is 'self-contained' in the static class containing that method. The key though is that the method gets an IConfiguration from the Startup class.

I've worked with DI in Azure Functions in past but haven't come across this specific requirement yet.

I'm using the IConfiguration to bind to a concrete class with properties matching settings from both my local.settings.json as well as the dev/production application settings when the Function is deployed in Azure.

CosmosDbClientSettings.cs

/// <summary> /// Holds configuration settings from local.settings.json or application configuration /// </summary>     public class CosmosDbClientSettings {     public string CosmosDbDatabaseName { get; set; }     public string CosmosDbCollectionName { get; set; }     public string CosmosDbAccount { get; set; }     public string CosmosDbKey { get; set; } } 

BootstrapCosmosDbClient.cs

public static class BootstrapCosmosDbClient {     /// <summary>     /// Adds a singleton reference for the CosmosDbService with settings obtained by injecting IConfiguration     /// </summary>     /// <param name="services"></param>     /// <param name="configuration"></param>     /// <returns></returns>     public static async Task<CosmosDbService> AddCosmosDbServiceAsync(         this IServiceCollection services,         IConfiguration configuration)     {         CosmosDbClientSettings cosmosDbClientSettings = new CosmosDbClientSettings();         configuration.Bind(nameof(CosmosDbClientSettings), cosmosDbClientSettings);          CosmosClientBuilder clientBuilder = new CosmosClientBuilder(cosmosDbClientSettings.CosmosDbAccount, cosmosDbClientSettings.CosmosDbKey);         CosmosClient client = clientBuilder.WithConnectionModeDirect().Build();         CosmosDbService cosmosDbService = new CosmosDbService(client, cosmosDbClientSettings.CosmosDbDatabaseName, cosmosDbClientSettings.CosmosDbCollectionName);         DatabaseResponse database = await client.CreateDatabaseIfNotExistsAsync(cosmosDbClientSettings.CosmosDbDatabaseName);         await database.Database.CreateContainerIfNotExistsAsync(cosmosDbClientSettings.CosmosDbCollectionName, "/id");          services.AddSingleton<ICosmosDbService>(cosmosDbService);          return cosmosDbService;     } } 

Startup.cs

public class Startup : FunctionsStartup {      public override async void Configure(IFunctionsHostBuilder builder)     {         builder.Services.AddHttpClient();         await builder.Services.AddCosmosDbServiceAsync(**need IConfiguration reference**); <--where do I get IConfiguration?     } } 

Obviously adding a private field for IConfiguration in Startup.cs won't work as it needs to be populated with something and I've also read that using DI for IConfiguration isn't a good idea.

I've also tried using the options pattern as described here and implemented as such:

builder.Services.AddOptions<CosmosDbClientSettings>()     .Configure<IConfiguration>((settings, configuration) => configuration.Bind(settings)); 

While this would work to inject an IOptions<CosmosDbClientSettings> to a non-static class, I'm using a static class to hold my configuration work.

Any suggestions on how I can make this work or a possible workaround? I'd prefer to keep all the configuration in one place (bootstrap file).

like image 471
Jason Shave Avatar asked Dec 24 '19 23:12

Jason Shave


People also ask

How do I use Azure function configuration?

To begin, go to the Azure portal and sign in to your Azure account. In the search bar at the top of the portal, enter the name of your function app and select it from the list. Under Settings in the left pane, select Configuration.

What is Dependency Injection in Azure?

Azure Functions supports the dependency injection (DI) software design pattern, which is a technique to achieve Inversion of Control (IoC) between classes and their dependencies. Dependency injection in Azure Functions is built on the . NET Core Dependency Injection features.


1 Answers

As of version 1.1.0 of Microsoft.Azure.Functions.Extensions you can do the following:

public class Startup : FunctionsStartup {     public override void Configure(IFunctionsHostBuilder builder)     {         var configuration = builder.GetContext().Configuration;         builder.Services.AddCosmosDbService(configuration);     } } 

Unfortunately it still does not support async configuration, so you will still have to block waiting for the task to finish or use the trick described by @Nkosi's answer.

like image 56
Casper Avatar answered Oct 16 '22 23:10

Casper