'Problems with user secrets in .Net console apps

I've created a .Net 6 console app. I added user secrets, but I only get the values defined in the appsettings.json file. I use Visual Studio Professional 2022 version 17.0.4.

Initial steps

  1. Create a new .Net 6 console app from Visual Studio 2022's project templates.
  2. Install the Microsoft.Extensions.Hosting nuget package (version 6.0.0).
  3. Install the Microsoft.Extensions.Configuration.UserSecrets nuget package (version 6.0.0).
  4. Add the appsettings.json file and set Copy to Output Directory to Copy always.
  5. Right-click on the project and select Manage User Secrets.

Code

Program.cs

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var host = Host.CreateDefaultBuilder()
                .ConfigureServices((context, services) => 
                {
                    services.Configure<GlobalSettings>(context.Configuration.GetSection("GlobalSettings"));
                    services.AddTransient<Worker>();
                })
                .Build();

var work = host.Services.GetRequiredService<Worker>();
await work.ExecuteAsync();

Worker.cs

using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

public class Worker
{
    private readonly ILogger<Worker> _logger;
    private readonly GlobalSettings _globalSettings;

    public Worker(ILogger<Worker> logger, IOptions<GlobalSettings> globalSettings)
    {
        _logger = logger;
        _globalSettings = globalSettings.Value;
    }

    public async Task ExecuteAsync()
    {
        _logger.LogInformation(_globalSettings.Foo);
        _logger.LogInformation(_globalSettings.Bar);
        await Task.CompletedTask;
    }
}

GlobalSettings.cs:

public class GlobalSettings
{
    public string Foo { get; set; }
    public string Bar { get; set; }
}

.csproj:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>disable</Nullable>
    <UserSecretsId>deedd476-f5d6-47f4-982e-1645c89789c7</UserSecretsId>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="6.0.0" />
    <PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.0" />
  </ItemGroup>
  <ItemGroup>
    <None Update="appsettings.json">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </None>
  </ItemGroup>
</Project>

appsettings.json:

{
    "GlobalSettings": {
        "Foo": "Normal Foo",
        "Bar": "Normal Bar"
    }
}

secrets.json:

{
    "GlobalSettings": {
        "Foo": "Secret Foo",
        "Bar": "Secret Bar"
    }
}

What I've tried

  • Checked whether the user secret id in csproj matched the folder, which it did: C:\Users\Dennis\AppData\Roaming\Microsoft\UserSecrets\deedd476-f5d6-47f4-982e-1645c89789c7
  • Rebuilded the project.
  • Closed Visual Studio 2022 and ran it again as administrator.
  • Created a new project from scratch.
  • Compared the code with one of my colleague's projects. I couldn't find any difference, but his code works when I run it.
  • Changed IOptionsSnapshot to IOptions and IOptionsMonitor.
  • Changed AddTransient to AddSingleton.
  • Did the same steps, but with a .Net 5 project instead.

Thanks.



Solution 1:[1]

I'd misunderstood the way the Host.CreateDefaultBuilder method worked. According to the documentation (docs):

load app IConfiguration from User Secrets when EnvironmentName is 'Development' using the entry assembly

My environment is Production (probably a fallback value). It worked in my colleague's project because it included a launchSettings.json file with the DOTNET_ENVIRONMENT environment variable set to Development.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1