Reputation: 1054
I have this weird issue where in one of the test projects in my solution the associated user secrets work well but in another new project they are not read at all, and when looking at the ConfigurationBuilder the FileProvider.Root is set to the debug folder.
To test I've put a secrets.json file in the debug folder and it indeed got read.
The code for reading the config is pretty similar between the solutions and looks like this:
public IConfigurationRoot GetConfig()
{
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddUserSecrets<ConfigClass1>()
.AddUserSecrets<ConfigClass2>()
...
.Build();
return configuration;
}
EDIT: The project does contain the UserSecretsId:
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<UserSecretsId>bfe3...</UserSecretsId>
<OutputType>Library</OutputType>
</PropertyGroup>
Upvotes: -1
Views: 1182
Reputation: 5312
I just came across this problem as well when trying to add UserSecrets in a net 6 docker container.
The path you (and me) are getting stems from:
The JsonConfigurationSource which UserSecrets use under the hood allows passing null
as a file provider, and the JsonConfigurationSource will try to repair this by defaulting to AppContext.BaseDirectory ?? string.Empty
.
Wrapping it back up, the provider initially is null due to this part:
which ultimately tries to determine whether the result of
https://source.dot.net/#Microsoft.Extensions.Configuration.UserSecrets/PathHelper.cs,26
public static string GetSecretsPathFromSecretsId(string userSecretsId)
{
if (string.IsNullOrEmpty(userSecretsId))
{
throw new ArgumentException(SR.Common_StringNullOrEmpty, nameof(userSecretsId));
}
int badCharIndex = userSecretsId.IndexOfAny(Path.GetInvalidFileNameChars());
if (badCharIndex != -1)
{
throw new InvalidOperationException(
string.Format(
SR.Error_Invalid_Character_In_UserSecrets_Id,
userSecretsId[badCharIndex],
badCharIndex));
}
const string userSecretsFallbackDir = "DOTNET_USER_SECRETS_FALLBACK_DIR";
// For backwards compat, this checks env vars first before using Env.GetFolderPath
string? appData = Environment.GetEnvironmentVariable("APPDATA");
string? root = appData // On Windows it goes to %APPDATA%\Microsoft\UserSecrets\
?? Environment.GetEnvironmentVariable("HOME") // On Mac/Linux it goes to ~/.microsoft/usersecrets/
?? Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
?? Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)
?? Environment.GetEnvironmentVariable(userSecretsFallbackDir); // this fallback is an escape hatch if everything else fails
if (string.IsNullOrEmpty(root))
{
throw new InvalidOperationException(SR.Format(SR.Error_Missing_UserSecretsLocation, userSecretsFallbackDir));
}
return !string.IsNullOrEmpty(appData)
? Path.Combine(root, "Microsoft", "UserSecrets", userSecretsId, SecretsFileName)
: Path.Combine(root, ".microsoft", "usersecrets", userSecretsId, SecretsFileName);
}
is valid.
As you can see, the GetSecretsPathFromSecretsId is trying quite a few options in order to determine the location of the secrets.json containing your secrets. In my case it defaulted to the /home directory since there is no appdata on linux. I wasn't expecting this, and because I did not mount my user secrets into that non-default directory there just wasn't a directory at all, so the checks I lined out determined my fileprovider to be null and defaulted to AppContext.BaseDirectory.
Hope this helps understanding the issue.
Upvotes: 2