I am new to .Net Core and trying to get a value from the appsettings.json
file but I have missed something very basic. Please let me know what I have done wrong...
Here is the code...
Program.cs
WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(Directory.GetCurrentDirectory());
})
Startup.cs
public IConfiguration Configuration { get; private set; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
services.Configure<EmailSettings>(Configuration.GetSection("EmailSettings"));
}
Web API Controller
private readonly IConfiguration config;
public EmailController(IConfiguration configuration)
{
if (configuration != null)
{
config = configuration;
}
}
Action Method
var emailTemplatesRelativePath = config.GetSection("EmailSettings");
var email = config.GetValue<string>("Email");
Both the above lines are returning null values for both GetSection
and GetValue
appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Trace",
"Microsoft": "Information"
}
},
"ConnectionStrings": {
"FCRContext": "server=xxx;database=xxx;user id=xxx;password=xxx"
},
"AllowedHosts": "*",
"EmailSettings": {
"EmailTemplatesPath": "EmailTemplates"
},
"Email": "[email protected]"
}
Accessing the configuration in the Controller works a little different than in the Startup.cs. I did this a while back, just follow these steps:
Nuget: Microsoft.Extensions.Configuration.Binder
Put all the Configuration you want to access in your Controller into one Section, e.g. "EmailSettings":
appsettings.json
{
"EmailSettings": {
"EmailTemplatesPath": "EmailTemplates",
"Email": "[email protected]"
}
}
Then Create a Class in your Web API Project called EmailSettings.cs
:
EmailSettings.cs
public class EmailSettings
{
public string EmailTemplatesPath { get; set; }
public string Email { get; set; }
}
Then bind your Config values to an Instance of the EmailSettings
Class in Startup.cs
and add that Object to the Dependency Injection Container:
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
...
EmailSettings emailSettings = new EmailSettings();
Configuration.GetSection("EmailSettings").Bind(emailSettings);
services.AddSingleton(emailSettings);
}
Now you can request your Configuration in the Api Controller by simply adding it to the Constructor like this:
Web API Controller
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
EmailSettings _emailSettings;
public ValuesController(EmailSettings emailSettings)
{
_emailSettings = emailSettings;
}
....
}
Just tried this again in my current Project (.NET Core 2.2 Web Api) and it worked. I put a Breakpoint in the ValuesController Constructor and the _emailSettings Object contained the values from the appsettings.json
file. You should be able to just Copy & Paste this! Have fun! :)
When hosting in-process inside of IIS (or IIS Express), Directory.GetCurrentDirectory()
will return a different path to that which is returned when running out-of-process. Up until ASP.NET Core 2.1, IIS-based hosting was always out-of-process, but ASP.NET Core 2.2 introduces the ability to run in-process (which is the default when creating a new project).
When running out-of-process, Directory.GetCurrentDirectory()
will return the path to your ASP.NET Core application itself, whereas when running in-process, it will return the path to IIS (or IIS Express, e.g. "C:\Program Files\IIS Express").
From your question, the relevant code is this:
WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(Directory.GetCurrentDirectory());
})
Here, before you make a call to SetBasePath
, the IConfigurationBuilder
has already been set up to use the correct path. Your call itself is overriding this path, setting it to e.g. "C:\Program Files\IIS Express". With this overridden base-path, your appsettings.json
et al files are no longer found, as they do not live in e.g. "C:\Program Files\IIS Express", and so no configuration is loaded from these files.
The solution is simply to remove your call to ConfigureAppConfiguration
so that the base-path does not get overridden. I realise you've already discovered this, but I wanted to make sure you had an explanation as to what was going wrong here.
You made a simple mistake and forgot to add "Email" into "EmailSettings". Update your json as shown below and get the Email with config.GetSection("EmailSettings")["Email"];
"EmailSettings": {
"EmailTemplatesPath": "EmailTemplates",
"Email": "[email protected]"
},
Hope this solves your problem.
Edit:
If you wanna get those values from appsettings to anything other than startup, you should load those config values into a settings class and then inject appropiate IOptions instance to the method constructor in which you want to use those settings. To do so, please see my answer here.
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