Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

configuration.getValue or configuration.getsection always returns null

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]"
}
like image 323
Naveed Butt Avatar asked Dec 29 '18 16:12

Naveed Butt


3 Answers

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! :)

like image 174
Robert Bantele Avatar answered Oct 23 '22 02:10

Robert Bantele


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.

like image 22
Kirk Larkin Avatar answered Oct 23 '22 02:10

Kirk Larkin


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.

like image 3
Hasan Avatar answered Oct 23 '22 00:10

Hasan