Configuration Load and Dotnet User Secrets

Configuration Load and Dotnet User Secrets

Cannot create instance of type 'System.String' because it has multiple public parameterized constructors.

ยท

2 min read

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": "๐Ÿ––"
    }
}

References