Binding a configuration to an object graph in .NET Core 2.0

15,334

Solution 1

You can still do both of these. Since you are in a console application, and as such likely not using the ASP.NET Core metapackage, you need to make sure to have the correct dependencies.

In order to bind the configuration to an object, you need the Microsoft.Extensions.Configuration.Binder package. Then, both solutions should work just fine.


Btw. even if you are in a console application, you could still make use of the dependency injection container that comes with ASP.NET Core. I’ve personally found it very simple to set up, so if you can still modify your application to use it, it might be worth it. The setup would just look like this:

var configuration = new ConfigurationBuilder()
    .AddJsonFile("config.json", optional: false)
    .Build();

var services = new ServiceCollection();
services.AddOptions();

// add your services here
services.AddTransient<MyService>();
services.AddTransient<Program>();

// configure options
services.Configure<AppSettings>(configuration.GetSection("App"));

// build service provider
var serviceProvider = services.BuildServiceProvider();

// retrieve main application instance and run the program
var program = serviceProvider.GetService<Program>();
program.Run();

Then, all your registered services can take dependencies just like they would do in ASP.NET Core. And to consume your configuration, you could then inject the IOptions<AppSettings> type like usually.

Solution 2

I was still having issues with this until I finally figured it out today.

The code was running without issues, but all the properties were still null, even after binding. I was doing this:

public class AppSettings
{
    public string MyProperty
}

and it turns out you have to do this:

public class AppSettings
{
    public string MyProperty { get; set; }
}

It only works if your class has Properties, not Fields. This wasn't clear to me.

Solution 3

If you want to register the config during Startup add this to Startup.cs:

services.Configure<AppSettings>(Configuration.GetSection("App"));

which you can then access by injecting an instance of IOptions<>:

private readonly AppSettings _appSettings;
public MyClass(IOptions<AppSettings> appSettings) {
    _appSettings = appSettings.Value;
}

Solution 4

This is how I bind my setting objects and add them as singleton in .Net Core 3.0

public void ConfigureServices(IServiceCollection services)
        {
            var jwtSettings = new JwtSettings();
            Configuration.Bind(jwtSettings);
            services.AddSingleton(jwtSettings);

            var databaseSettings = new DatabaseSettings();
            Configuration.Bind(databaseSettings);
            services.AddSingleton(databaseSettings);


            services.AddControllersWithViews();
        }

My setting objects looks like this:

public class DatabaseSettings
    {
        public string ConnectionString { get; set; }
        public string DatabaseName { get; set; }
    }

public class JwtSettings
    {
        public string Secret { get; set; }
        public string Lifetime { get; set; }
    }

My appsettings.json file looks like below:

{
  "DatabaseSettings": {
    "ConnectionString": "mongodb://localhost:27017",
    "DatabaseName": "TestDb"
  },
  "JwtSettings": {
    "Secret": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    "Lifetime": "170"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}
Share:
15,334
Joshua Walsh
Author by

Joshua Walsh

Updated on June 13, 2022

Comments

  • Joshua Walsh
    Joshua Walsh over 1 year

    I'm making a .NET Core 2.0 app and I need to configure it. I'm looking at this documentation and it seems that in .NET Core 1.0 you could do:

    var appConfig = new AppSettings();
    config.GetSection("App").Bind(appConfig);
    

    And in .NET Core 1.1 you could do:

    var appConfig = config.GetSection("App").Get<AppSettings>();
    

    But neither Bind nor Get exist in .NET Core 2.0. What's the new way to achieve this?

    Thanks,

    Josh

  • Joshua Walsh
    Joshua Walsh almost 6 years
    Isn't that only for Asp.NET/MVC? I'm just making a console app.
  • JLe
    JLe almost 6 years
    Oh, my bad. It is for ASP.NET, but it should work for a Console app as well, but you would have to add the packages.
  • Joshua Walsh
    Joshua Walsh over 5 years
    This mostly solved my problem, but I did still have an issue where the values were all being left as null. My answer explains how I resolved that.
  • Rob
    Rob about 5 years
    Thanks Heaps!!, spent hours trying to solve this exact issue with the values always returning as null and the inspector always showing 'configuration.getsection' value as null. So many questions have been posted on the null value; bet a whole lot of people have the same problem
  • natenho
    natenho over 4 years
    OptionsHelper.CreateOptions won't return anything
  • Oliver
    Oliver over 4 years
    What have you tried, what didn't work. Have you stepped through it with the debugger. Where didn't you get anything? One possibility could be that FirstOrDefaultMatchingType() didn't find the matching type, cause the assembly containing the destination type isn't loaded. So a little more informations would be helpful.
  • Charles Prakash Dasari
    Charles Prakash Dasari over 4 years
    Thanks! Also, properties with public setters (required).
  • Dustin C
    Dustin C over 2 years
    I'm not sure why I had to specify the section name but this finally worked for me once I told it which section to retrieve, like this: Configuration.GetSection("JwtSettings").Bind(jwtSettings);
  • Jérôme MEVEL
    Jérôme MEVEL over 2 years
    As a side note, there's no point having public fields. Your fields should never be public otherwise just use properties