I'm unable to retrieve the value set in appsettings.json, when I run the code below, I get an error System.NullReferenceException: 'Object reference not set to an instance of an object.'
What am I doing wrong?
public static IConfigurationRoot Configuration { get; }
....
string facebookApiId = Configuration.GetValue<string>("Authentication:Facebook:AppId");
appSettings.json
"Authentication": {
"Facebook": {
"IsEnabled": "false",
"AppId": "somevalue1",
"AppSecret": "somevalue2"
},
"Google": {
"IsEnabled": "false",
"ClientId": "somevalue3",
"ClientSecret": "somevalue4"
}
Startup.cs
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; }
In your code you actually have 2 (two) Configuration
properties, one in Startup
, which is good, as it's being populated and stored in instance field, and one in unnamed controller, which is static
and seems to be never instantiated.
According MSDN article about the configuration, recommended way to provide your options to the controllers is to implement basic option and configuration object logic, something like this:
// option mapping classes
public class FacebookOptions
{
// maybe string here
public bool IsEnabled { get; set; }
public string AppId { get; set; }
public string AppSecret { get; set; }
}
public class GoogleOptions
{
// maybe string here
public bool IsEnabled { get; set; }
public string ClientId { get; set; }
public string ClientSecret { get; set; }
}
// load configuration
public Startup(IHostingEnvironment env)
{
// Set up configuration sources.
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appSettings.json", optional: true, reloadOnChange: true);
Configuration = builder.Build();
}
// map the configuration to object
public void ConfigureServices(IServiceCollection services)
{
// Adds services required for using options.
services.AddOptions();
// Register the IConfiguration instance which options binds against.
services.Configure<FacebookOptions>(Configuration.GetSection("Facebook"));
services.Configure<GoogleOptions>(Configuration.GetSection("Google"));
// Add framework services.
services.AddMvc();
}
Now you can easily get the options on your controller via dependency injection:
public class GoogleController : Controller
{
private readonly GoogleOptions _googleOptions;
public GoogleController(IOptions<GoogleOptions> googleOptionsAccessor)
{
_googleOptions = googleOptionsAccessor.Value;
}
}
If you need a whole configuration, you can add some generic class containing all the options and use an object graph mapping from the same article:
public class Authentication
{
public FacebookOptions Google { get; set; }
public GoogleOptions Google { get; set; }
}
// load configuration
public Startup(IHostingEnvironment env)
{
// Set up configuration sources.
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appSettings.json", optional: true, reloadOnChange: true);
Configuration = builder.Build();
var options = new Authentication();
config.GetSection("Authentication").Bind(options);
}
Edit: Make sure that your classes and configuration sections are named equally as this is important, as turned out.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With