1

I need to get the connectionstring from usersecrets. I tried getting it that way:

CosmosClient cosmos = new CosmosClient("CosmosConnectionString", new CosmosClientOptions
        {
            ConnectionMode = ConnectionMode.Gateway
        });

But this doesn't work, since the CosmosClient understands only the literal string. I tried injecting Azure Functions with usersecrets, and for that I made a startup class:

    [assembly: FunctionsStartup(typeof(Startup))]
namespace AltProject
{
    public class Startup : FunctionsStartup
    {
        // override configure method
        public override void Configure(IFunctionsHostBuilder builder)
        {
            var config = new ConfigurationBuilder()
               .SetBasePath(Environment.CurrentDirectory)
               .AddJsonFile("appsettings.json", true)
               .AddUserSecrets(Assembly.GetExecutingAssembly(), false)
               .AddEnvironmentVariables()
               .Build();
           
            builder.Services.AddSingleton<IConfiguration>(config);
            foreach (DictionaryEntry de in Environment.GetEnvironmentVariables())
                Console.WriteLine("  {0} = {1}", de.Key, de.Value);            // register your other services
        }
    }

}

Then I tried to get the connectionstring in this way in the CosmosClient:

      CosmosClient cosmos = new CosmosClient(System.Environment.GetEnvironmentVariable("CosmosConnectionString", EnvironmentVariableTarget.Process), new CosmosClientOptions
        {
            ConnectionMode = ConnectionMode.Gateway
        });

But this gives me no results, it seems the Environment Values don't get injected with the usersecrets. Is there a way to make this work?

nana
  • 51
  • 6

2 Answers2

1

All answers/blog posts I've seen so far indicate that DI is a prerequisite, requiring a startup class implementation that is not present in the VS Azure Function template, but it's actually fairly easy to access a user secret without fiddling with local.settings.json and all the boiler plate involved in setting up DI:

 ConfigurationBuilder builder = new();
 builder.AddUserSecrets(Assembly.GetExecutingAssembly());
 var configuration = builder.Build();
 var secret = configuration.GetValue<string>("MY_SECRET");

You will naturally need a code switch around the above for running deployed in Azure, either like this or with preprocessor directives and call

var secret = Environment.GetEnvironmentVariable($"MY_SECRET", EnvironmentVariableTarget.Process);

Non the less it's alot less hassle than setting up DI IMHO

noontz
  • 1,782
  • 20
  • 29
0

Full example at: https://github.com/Azure/azure-cosmos-dotnet-v3/tree/master/Microsoft.Azure.Cosmos.Samples/Usage/AzureFunctions

You should be able to read the config in your Startup without issues. Assuming your appsettings.json contains a key called CosmosConnectionString or you are adding it via the Functions App Settings:

[assembly: FunctionsStartup(typeof(AltProject.Startup))]
namespace AltProject
{
    private static readonly IConfigurationRoot configuration = new ConfigurationBuilder()
                .SetBasePath(Environment.CurrentDirectory)
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                .AddEnvironmentVariables()
                .Build();

    public override void Configure(IFunctionsHostBuilder builder)
    {
        builder.Services.AddSingleton((s) => {
            string connectionString = configuration["CosmosConnectionString"];
            if (string.IsNullOrEmpty(connectionString))
            {
                throw new ArgumentNullException("CosmosConnectionString empty or not set at appsettings.json file or your Azure Functions Settings.");
            }

            return new CosmosClient(connectionString, new CosmosClientOptions
            {
                ConnectionMode = ConnectionMode.Gateway
            });
        });
    }
}

You can then inject the CosmosClient in your Functions:

public class MyFunction
{
    private CosmosClient cosmosClient;
    public MyFunction(CosmosClient cosmosClient)
    {
        this.cosmosClient = cosmosClient;
    }


    [FunctionName("CosmosClient")]
    public async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
        ILogger log)
    {
        // use this.cosmosClient
    }
}
Matias Quaranta
  • 13,907
  • 1
  • 22
  • 47