Configuration Load and Dotnet User Secrets
Cannot create instance of type 'System.String' because it has multiple public parameterized constructors.
I was getting this error while attempting to load up a appSettings.json
for an integration test:
'config.GetSection(settingsName).Get()' threw an exception of type 'System.InvalidOperationException' Data: {System.Collections.ListDictionaryInternal} HResult: -2146233079 HelpLink: null InnerException: null Message: "Cannot create instance of type 'System.String' because it has multiple public parameterized constructors." Source: "Microsoft.Extensions.Configuration.Binder" StackTrace: " at Microsoft.Extensions.Configuration.ConfigurationBinder.CreateInstance(Type type, IConfiguration config, BinderOptions options)\r\n at Microsoft.Extensions.Configuration.ConfigurationBinder.BindInstance(Type type, BindingPoint bindingPoint, IConfiguration config, BinderOptions options, Boolean isParentCollection)\r\n at Microsoft.Extensions.Configuration.ConfigurationBinder.BindProperty(PropertyInfo property, Object instance, IConfiguration config, BinderOptions options)\r\n at Microsoft.Extensions.Configuration.ConfigurationBinder.BindProperties(Object instance, IConfiguration configuration, BinderOptions options)\r\n at Microsoft.Extensions.Configuration.ConfigurationBinder.BindInstance(Type type, BindingPoint bindingPoint, IConfiguration config, BinderOptions options, Boolean isParentCollection)\r\n at Microsoft.Extensions.Configuration.ConfigurationBinder.Get(IConfiguration configuration, Type type, Action1 configureOptions)\r\n at Microsoft.Extensions.Configuration.Confi gurationBinder.Get[T](IConfiguration configuration, Action1 configureOptions)\r\n at Microsoft.Extensions.Configuration.ConfigurationBinder.Get[T](IConfiguration configuration)" TargetSite: {System.Object CreateInstance(System.Type, Microsoft.Extensions.Configuration.IConfiguration, Microsoft.Extensions.Configuration.BinderOptions
"Cannot create instance of type 'System.String' because it has multiple public parameterized constructors."
WTF.
Settings/Configuration class:
public class SomeSettings
{
public string? Key { get; set; }
}
Test Class Initialization:
IConfigurationRoot config = new ConfigurationBuilder()
.AddJsonFile("appSettings.test.json", false, false)
.AddUserSecrets<SomeIntegrationTest>()
var services = new ServiceCollection();
services.AddSingleton(Log.Logger)
.AddSomeService(config)
.AddSingleton<ISomeService, SomeService>();
ServiceProvider provider = services.BuildServiceProvider();
_someService = provider.GetRequiredService<ISomeService>();
The extension class and method:
public static class SomeServiceExtensions
{
public static IServiceCollection AddIovationClient(this IServiceCollection services
, IConfigurationRoot config)
{
var someSettings = config.GetSection(nameof(SomeSettings)).Get<ISomeService>(); // Exception here.
return services.AddSingleton(someSettings)
.AddSingleton(someService);
}
}
This is the appSettings.test.json
:
{
"SomeSettings": {
"SomeOtherConfig": "๐"
}
}
The user secret was added with:
dotnet user-secrets set "SomeSettings:Key" "SUPER_SUPER_SECRET_SECRET" --project "$ProjectPath"
Retracing steps to before this error occurred, which was before running dotnet user-secrets
, I removed the secrets from:
%APPDATA%\Microsoft\UserSecrets\<user_secrets_id>\secrets.json
Solution
Turns out that the appSettings.json
must have the the key/name/property
value populated for it to be overridden by the UserSecrets
:
{
"SomeSettings": {
"Key": "SECRET_TO_BE_POPULATED", // Must be defined
"SomeOtherConfig": "๐"
}
}