User Secrets error is being generated in a CI/CD pipeline, when secrets.json file shouldn't be expected.
Steps:
Code runs locally, but fails in CI/CD pipelines, with error:
"The configuration file 'secrets.json' was not found and is not optional."
Expected:
Code runs without the secrets.json file being present Configuration .NET 6, Microsoft.Extensions.Configuration.UserSecrets: 6.0.0-preview.1.21102.12
Regression? This works in .NET 5, Microsoft.Extensions.Configuration.UserSecrets: 5.0.0.*
System.IO.FileNotFoundException: The configuration file 'secrets.json' was not found and is not optional. The physical path is '/home/runner/work/UserSecretsRegression/UserSecretsRegression/UserSecrets/UserSecrets.Tests/bin/Release/net6.0/secrets.json'.
Stack Trace:
at Microsoft.Extensions.Configuration.FileConfigurationProvider.HandleException(ExceptionDispatchInfo info)
at Microsoft.Extensions.Configuration.FileConfigurationProvider.Load(Boolean reload)
at Microsoft.Extensions.Configuration.FileConfigurationProvider.Load()
at Microsoft.Extensions.Configuration.ConfigurationRoot..ctor(IList`1 providers)
at Microsoft.Extensions.Configuration.ConfigurationBuilder.Build()
at UserSecrets.Tests.UnitTest1.TestMethod1() in /home/runner/work/UserSecretsRegression/UserSecretsRegression/UserSecrets/UserSecrets.Tests/UnitTest1.cs:line 13
Santiago Trujillo
https://github.com/dotnet/runtime/issues/48485
Basically, it's a new feature in .NET6 that 'secrets.json' is not optional by default!
AddUserSecrets(this IConfigurationBuilder configuration, Assembly assembly, bool optional);
That 'optional' parameter should be set to 'true' in your code.
var configuration = new ConfigurationBuilder()
.AddEnvironmentVariables()
.AddCommandLine(args)
.AddJsonFile("appsettings.json")
.AddUserSecrets<Program>(true)
.Build();
Unlike environment variables, user secrets are placed in a settings file similar to appsettings.json
. Having similar structured off-project settings is great when you need to copy keys and values between files and there is support for adding, removing, and listing values as I will show you later in this post.
To understand user secrets, let's resume the example from the previous post. In there I had an appsettings.json
file looking like this:
{
"AppSettings": {
"ConnectionString": "http://localhost:9000"
},
...
}
In order to override the AppSettings:ConnectionString
setting on individual machines, each user needs to add a user secret with the same name. The easiest approach is to right-click the project and select Manage User Secrets:
This creates and opens a new empty JSON file named secrets.json
. The file is placed beneath C:\Users\<username>\AppData\Roaming\Microsoft\UserSecrets\<id>
where <username>
matches your Windows user and is a randomly generated GUID. The important thing to notice here is that the file is located outside your project directory. In order to "bind" the secrets.json
file location to your project, Visual Studio added a bit of markup to the csproj
file:
<PropertyGroup>
<UserSecretsId>dda25df4-9a88-4a7e-8502-2134b74e4729</UserSecretsId>
</PropertyGroup>
In case you are not using Visual Studio, you can generate a random GUID and add the <UserSecretsId>
manually.
In case you want to override the AppSettings:ConnectionString
setting, add a similar structure to the secrets.json
file:
{
"AppSettings": {
"ConnectionString": "http://localhost:9000?user=mehdidaustany&password=1234"
}
}
You can also collapse settings like this:
{
"AppSettings:ConnectionString": "http://localhost:9000?user=mehdidaustany&password=1234"
}
Finally add created secrets.json
in the root of your project.
In .net 6.0, the application needs secret.json to run. in any case, if you are migrating from .net core 3.1 or .net 5.0 in order to run your application in .net 6.0:
dotnet user-secrets init
in your project folder using command-line tools.secret.json
file in your app domain ...\bin\Debug\net6.0
. It doesn't matter if your secret.json
file is empty for now.Hit F5 and run your application!