0

In my function app (.NET 7.0, Isolated Worker), I have one particular dependency that uses an API key, something that needs to be put in a secret store. I'm using User Secrets for local development, but I'm stuck on how to access those secret values when configuring services for dependency injection:

// secrets.json

{
  "apiKey": "1234567890"
}
// Program.cs

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .ConfigureServices(s =>
    {
        string apiKey = ???;  // how to access user secrets here?
        s.AddScoped<IMyDependency>(sp => new MyDependency(apiKey));
    });
    .Build();
}

host.Run();

There is guidance from Microsoft on using User Secrets:

But neither of these solutions offer what I need, which is a way to access user secret values when setting up dependency injection. Instead, the recommended solution makes the configuration values themselves injected dependencies, which I can't use.

Things I've tried:

  • Using Environment.GetEnvironmentVariable, which doesn't return a value.
  • Adding the user secrets configuration provider using builder.AddUserSecrets. I don't know whether this is necessary to do, but even if it is, I still don't know how to access the configuration when setting up DI.
nmpauls
  • 144
  • 1
  • 9

1 Answers1

2

I have followed the same MSDoc which you have provided to set the UserSecrets.

Thanks @damienbod and SOThread for the code.

My .csproj file:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net7.0</TargetFramework>
    <AzureFunctionsVersion>v4</AzureFunctionsVersion>
    <OutputType>Exe</OutputType>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <UserSecretsId>****-d46c-****-9752-04-****</UserSecretsId>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.10.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.0.13" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.7.0" />
    <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="6.0.1" />
  </ItemGroup>
  <ItemGroup>
    <None Update="host.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="local.settings.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <CopyToPublishDirectory>Never</CopyToPublishDirectory>
    </None>
  </ItemGroup> 
   
  <ItemGroup>
    <Using Include="System.Threading.ExecutionContext" Alias="ExecutionContext" />
  </ItemGroup>
</Project>

Program.cs file:

 Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System.Reflection;

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .ConfigureAppConfiguration(con =>
    {      
        con.AddUserSecrets<Program>(optional:true,reloadOnChange:false);
    })
    .ConfigureServices(s =>
    {
        var config = s.BuildServiceProvider().GetService<IConfiguration>();
        string apiKey = config.GetValue<string>("apiKey");
    })
    .Build();
host.Run();

[edit] - I want to clarify and add for others searching that while it may seem obvious, the AddUserSecrets() format is the only way to get it to work for the newer Program.cs construct. The Startup example is everywhere, and AddUserSecrets() seems to be implicitly working without specifying but only for the Startup style. But the mention is NOWHERE that I could find on the Internet. Program is implicit, given there is no actual Startup class anymore.

I could not get User Secrets to work for the life of me without hard coding in the user sercets id, which is obviously not acceptable.

OutPut:

enter image description here

drewid
  • 2,737
  • 3
  • 16
  • 11
Harshitha
  • 3,784
  • 2
  • 4
  • 9