1

I am trying to bind some configurable settings. The values are provided via the app-settings.local.json. The Model to bind to is called Configurable Settings. I have attempted to follow a few tutorials and troubleshoot the issue:

  1. https://andrewlock.net/how-to-use-the-ioptions-pattern-for-configuration-in-asp-net-core-rc2/
  2. https://github.com/aspnet/Configuration/issues/411
  3. Cannot set Configuration from JSON appsettings file in .NET Core project
  4. ServiceCollection returns null for IOptions even though GetSection is working

I have attempted to follow the advice given here and apply it in my own application. I could not get it to work after 4 hours of trying. Either I lack the basic knowledge needed to implement this or I'm overlooking something.

My ConfigurableSettings class is structured as follows:

    public class ConfigurableSettings
    {
        public AppSettings _AppSettings;
        public DgeSettings _DgeSettings;
        
        public class AppSettings
        {
            [JsonProperty("SoftDelete")] 
            public bool SoftDelete { get; set; }
        }

        public class DgeSettings
        {
            [JsonProperty("zipFileUrl")] 
            public string zipFileUrl { get; set; }

            [JsonProperty("sourceFileUrl")] 
            public string sourceFileUrl { get; set; }
        }
    }

My ConfigureServices is structured as follows:

    public static void ConfigureServices(IServiceCollection serviceCollection, string[] args)
        {
            var serviceCollection = new ServiceCollection(); 
            
            serviceCollection.AddOptions();
            
            var configuration = new ConfigurationBuilder()
                                .SetBasePath(Directory.GetCurrentDirectory())
                                .AddJsonFile("app-settings.local.json", true)
                                .AddJsonFile("app-settings.json", false)
                                .Build();

            serviceCollection.Configure<ConfigurableSettings>(options => configuration.GetSection("AppSettings").Bind(options));
            serviceCollection.Configure<ConfigurableSettings>(options => configuration.GetSection("DgeSettings").Bind(options));

            var services = serviceCollection.BuildServiceProvider();
            var options = services.GetService<IOptions<ConfigurableSettings>>();

            serviceCollection.AddLogging(loggingBuilder =>
            {
                loggingBuilder.AddConfiguration(configuration.GetSection("Logging"));
                loggingBuilder.AddConsole();
                loggingBuilder.AddDebug();
            });

            serviceCollection.AddServices(configuration);
            serviceCollection.AddNopCommerceServices(configuration);

            serviceCollection.AddTransient<Comparator>();
            serviceCollection.AddTransient<UpdateManager>();
            serviceCollection.AddTransient<DgeRequestAuthenticator>();
            serviceCollection.AddTransient<ISourceConnector, DgeConnector>();
            serviceCollection.AddTransient<IDestinationConnector, NopCommerceConnector>();
        }

My app-settings.local.json is configured as follows:

{
  "AppSettings": {
    "SoftDelete": true
  },

  "DgeSettings": {
    "zipFileUrl" : "www.example-url.com",
    "sourceFileUrl" : "www.example-url.com"
  }
}

When I attempt to use it in a class, I call it in my constructor as follows:

private readonly ConfigurableSettings _settings;
        
        public AlphaBetaService(IOptions<ConfigurableSettings> settings)
        {
            _settings = settings.Value;
        }
    

Could someone help me to find out what I am doing wrong?

Rena
  • 30,832
  • 6
  • 37
  • 72
shinyshark
  • 81
  • 8
  • https://stackoverflow.com/questions/65546723/how-to-read-values-from-multiple-json-files-in-net-core/65547297#65547297 – Chetan Jun 14 '21 at 15:19
  • Does this answer your question? [How to read values from multiple json files in .Net Core?](https://stackoverflow.com/questions/65546723/how-to-read-values-from-multiple-json-files-in-net-core) – Chetan Jun 14 '21 at 15:19
  • @ChetanRanpariya It certainly helped me to get closer. I can see that it recognizes the data in my debugger, but it won't bind it to the model. Is it perhaps because I am using a difficult model? I Configure my AppSettings on ConfigurableSettings.AppSettings. – shinyshark Jun 14 '21 at 15:59

1 Answers1

0

Not sure how do you use ConfigureServices method in your project, actually the ConfigureServices in Startup.cs must either be parameterless or take only one parameter of type IServiceCollection.

Change your ConfigureServices like below:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        var configuration = new ConfigurationBuilder()
                            .SetBasePath(Directory.GetCurrentDirectory())
                            .AddJsonFile("app-settings.local.json", true)
                            .Build();
        services.Configure<ConfigurableSettings>(configuration);

        //...
    }
}

Also change your model design like below:

public class ConfigurableSettings
{
    public AppSettings AppSettings{ get; set; }
    public DgeSettings DgeSettings { get; set; }        
}
public class AppSettings
{
    [JsonProperty("SoftDelete")]
    public bool SoftDelete { get; set; }
}

public class DgeSettings
{
    [JsonProperty("zipFileUrl")]
    public string zipFileUrl { get; set; }

    [JsonProperty("sourceFileUrl")]
    public string sourceFileUrl { get; set; }
}
Rena
  • 30,832
  • 6
  • 37
  • 72
  • This wouldn't solve the problem because you cannot declare your model the way you've done. It will warn that a member with the same name is already declared. I fixed the issue by dumbing down my model. Now it's just ConfigurableSettings with two regions rather than two classes. – shinyshark Jun 15 '21 at 06:15
  • 1
    Please read carefully. The AppSettings and DgeSettings is outside the `ConfigurableSettings` not in it. Otherwise it will warn the same name is already declared. – Rena Jun 15 '21 at 06:22