By aman


2017-10-25 19:33:08 8 Comments

Not sure what am I missing here but I am not able to get the values from my appsettings.json in my .net core application. I have my appsettings.json as:

{
    "AppSettings": {
        "Version": "One"
    }
}

Startup:

public class Startup
{
    private IConfigurationRoot _configuration;
    public Startup(IHostingEnvironment env)
    {
        _configuration = new ConfigurationBuilder()
    }
    public void ConfigureServices(IServiceCollection services)
    {
      //Here I setup to read appsettings        
      services.Configure<AppSettings>(_configuration.GetSection("AppSettings"));
    }
}

Model:

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

Controller:

public class HomeController : Controller
{
    private readonly AppSettings _mySettings;

    public HomeController(IOptions<AppSettings> settings)
    {
        //This is always null
        _mySettings = settings.Value;
    }
}

_mySettings is always null. Is there something that I am missing here?

7 comments

@David Liang 2017-10-25 19:40:07

Thanks @Kirk for pointing it out that I shouldn't assume it's .NET Core 2.0!

Program and Startup class

.NET Core 2.x

You don't need to new IConfiguration in the Startup constructor. Its implementation will be injected by the DI system.

// Program.cs
public class Program
{
    public static void Main(string[] args)
    {
        BuildWebHost(args).Run();
    }

    public static IWebHost BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .Build();            
}

// Startup.cs
public class Startup
{
    public IHostingEnvironment HostingEnvironment { get; private set; }
    public IConfiguration Configuration { get; private set; }

    public Startup(IConfiguration configuration, IHostingEnvironment env)
    {
        this.HostingEnvironment = env;
        this.Configuration = configuration;
    }
}

.NET Core 1.x

You need to tell Startup to load the appsettings files.

// Program.cs
public class Program
{
    public static void Main(string[] args)
    {
        var host = new WebHostBuilder()
            .UseKestrel()
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseIISIntegration()
            .UseStartup<Startup>()
            .UseApplicationInsights()
            .Build();

        host.Run();
    }
}

//Startup.cs
public class Startup
{
    public IConfigurationRoot Configuration { get; private set; }

    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();

        this.Configuration = builder.Build();
    }
    ...
}


Getting Values

There are many ways you can get the value you configure from the app settings:

Let's say your appsettings.json looks like this:

{
    "ConnectionStrings": {
        ...
    },
    "AppIdentitySettings": {
        "User": {
            "RequireUniqueEmail": true
        },
        "Password": {
            "RequiredLength": 6,
            "RequireLowercase": true,
            "RequireUppercase": true,
            "RequireDigit": true,
            "RequireNonAlphanumeric": true
        },
        "Lockout": {
            "AllowedForNewUsers": true,
            "DefaultLockoutTimeSpanInMins": 30,
            "MaxFailedAccessAttempts": 5
        }
    },
    "Recaptcha": { 
        ...
    },
    ...
}

Simple Way

You can inject the whole configuration into the constructor of your controller/class (via IConfiguration) and get the value you want with a specified key:

public class AccountController : Controller
{
    private readonly IConfiguration _config;

    public AccountController(IConfiguration config)
    {
        _config = config;
    }

    [AllowAnonymous]
    public IActionResult ResetPassword(int userId, string code)
    {
        var vm = new ResetPasswordViewModel
        {
            PasswordRequiredLength = _config.GetValue<int>(
                "AppIdentitySettings:Password:RequiredLength"),
            RequireUppercase = _config.GetValue<bool>(
                "AppIdentitySettings:Password:RequireUppercase")
        };

        return View(vm);
    }
}

Options Pattern

The ConfigurationBuilder.GetValue<T> works great if you only need one or two values from the app settings. But if you want to get multiple values from the app settings, or you don't want to hard code those key strings in multiple places, it might be easier to use Options Pattern. The options pattern uses classes to represent the hierarchy/structure.

To use options pattern:

  1. Define classes to represent the structure
  2. Register the configuration instance which those classes bind against
  3. Inject IOptions<T> into the constructor of the controller/class you want to get values on

1. Define configuration classes to represent the structure

You can define classes with properties that need to exactly match the keys in your app settings. The name of the class does't have to match the name of the section in the app settings:

public class AppIdentitySettings
{
    public UserSettings User { get; set; }
    public PasswordSettings Password { get; set; }
    public LockoutSettings Lockout { get; set; }
}

public class UserSettings
{
    public bool RequireUniqueEmail { get; set; }
}

public class PasswordSettings
{
    public int RequiredLength { get; set; }
    public bool RequireLowercase { get; set; }
    public bool RequireUppercase { get; set; }
    public bool RequireDigit { get; set; }
    public bool RequireNonAlphanumeric { get; set; }
}

public class LockoutSettings
{
    public bool AllowedForNewUsers { get; set; }
    public int DefaultLockoutTimeSpanInMins { get; set; }
    public int MaxFailedAccessAttempts { get; set; }
}

2. Register the configuration instance

And then you need to register this configuration instance in ConfigureServices() in the start up:

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
...

namespace DL.SO.UI.Web
{
    public class Startup
    {
        ...
        public void ConfigureServices(IServiceCollection services)
        {
            ...
            var identitySettingsSection = 
                _configuration.GetSection("AppIdentitySettings");
            services.Configure<AppIdentitySettings>(identitySettingsSection);
            ...
        }
        ...
    }
}

3. Inject IOptions

Lastly on the controller/class you want to get the values, you need to inject IOptions<AppIdentitySettings> through constructor:

public class AccountController : Controller
{
    private readonly AppIdentitySettings _appIdentitySettings;

    public AccountController(IOptions<AppIdentitySettings> appIdentitySettingsAccessor)
    {
        _appIdentitySettings = appIdentitySettingsAccessor.Value;
    }

    [AllowAnonymous]
    public IActionResult ResetPassword(int userId, string code)
    {
        var vm = new ResetPasswordViewModel
        {
            PasswordRequiredLength = _appIdentitySettings.Password.RequiredLength,
            RequireUppercase = _appIdentitySettings.Password.RequireUppercase
        };

        return View(vm);
    }
}

@Kirk Larkin 2017-10-25 20:25:21

I think your answer assumes 2.0 - this might be the case but IConfiguration will likely not be set up or, iirc, even injectable in 1.x.

@David Liang 2017-10-25 20:44:13

@Kirk: thanks for pointing it out! I am really appreciated. :)

@Lukas Hieronimus Adler 2018-01-10 08:09:42

How can i access the Values in the Class which holds my Data?

@David Liang 2018-01-11 00:16:41

@LukasHieronimusAdler: See Controller sample section in the original question?? Access the value by doing IOptions<AppSettings> settings and settings.Value??

@Lukas Hieronimus Adler 2018-01-12 11:49:58

@DavidLiang if i change the appsettings.json file manually during runtime, my IOptions<AppSettings> settings Object doesn't get the changed values. Whats wrong? If added this: .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) For me, it should reload on an external change right?

@David Liang 2018-01-12 18:06:16

@LukasHieronimusAdler: You might want to use IOptionsSnapshot<T> instead of IOptions<T>. You can take a look at this article: offering.solutions/blog/articles/2017/02/17/…. I haven't had chance to try it myself though.

@Lukas Hieronimus Adler 2018-01-15 10:40:38

@DavidLiang yes its still working, but i cant access the IOptionsSnapshot<T> from normal Classes. If i pass the IOptionsSnapshot<T> in the constructor like in controller-classes its needed to pass this object manually but how can i access it? Hopefully you know what i mean. Thanks for your help

@David Liang 2018-01-15 18:24:08

I think you access IOptionsSnapshot<T> class the same way you access IOptions<T>? And in order for classes to be able to receive IOptionsSnapshot<T>, you just need to inject T in the Startup, same way with IOptions<T>! Please read through the article multiple times and find the Microsoft docs on this subject. Without taking a look at your source code, I don't get what problem you're facing. Sorry

@Syaiful Nizam Yahya 2018-07-13 01:50:04

Could you make it simple like a snippet?

@Aaron 2018-10-20 23:48:04

What a horrible step backwards from full stack .net

@mk_yo 2019-09-02 16:22:13

where is usage example? like getting actual settings in some controller

@David Liang 2019-09-03 18:46:01

@mk_yo: I've updated my answer with more examples. See if that makes sense to you

@Lizo Matala 2018-11-07 08:01:06

In my case it was simple as using the Bind() method on the Configuration object. And then add the object as singleton in the DI.

var instructionSettings = new InstructionSettings();
Configuration.Bind("InstructionSettings", instructionSettings);
services.AddSingleton(typeof(IInstructionSettings), (serviceProvider) => instructionSettings);

The Instruction object can be as complex as you want.

{  
 "InstructionSettings": {
    "Header": "uat_TEST",
    "SVSCode": "FICA",
    "CallBackUrl": "https://UATEnviro.companyName.co.za/suite/webapi/receiveCallback",
    "Username": "s_integrat",
    "Password": "[email protected]",
    "Defaults": {
    "Language": "ENG",
    "ContactDetails":{
       "StreetNumber": "9",
       "StreetName": "Nano Drive",
       "City": "Johannesburg",
       "Suburb": "Sandton",
       "Province": "Gauteng",
       "PostCode": "2196",
       "Email": "[email protected]",
       "CellNumber": "0833 468 378",
       "HomeNumber": "0833 468 378",
      }
      "CountryOfBirth": "710"
    }
  }

@sepideh dalirpour 2019-01-15 06:04:34

    public static void GetSection()
    {
        Configuration = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json")
            .Build();

        string BConfig = Configuration.GetSection("ConnectionStrings")["BConnection"];

    }

@Carlos ABS 2019-04-17 18:49:00

Incomplete answer

@Shadi Namrouti 2019-01-06 10:22:47

In the constructor of Startup class, you can access appsettings.json and many other settings using the injected IConfiguration object:

Startup.cs Constructor

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;

        //here you go
        var myvalue = Configuration["Grandfather:Father:Child"];

    }

public IConfiguration Configuration { get; }

Contents of appsettings.json

  {
  "Grandfather": {
    "Father": {
      "Child": "myvalue"
    }
  }

@Jacques Olivier 2019-04-17 06:24:25

It was the 'Configuration["Grandfather:Father:Child"]' syntax that helped me.

@jolySoft 2019-07-10 13:26:02

This is an outstanding answer in the way it is structured, clear and to the point. Great communication

@Aseem Gautam 2018-02-22 11:12:16

Adding to David Liang's answer for Core 2.0 -

appsettings.json file's are linked to ASPNETCORE_ENVIRONMENT variable.

ASPNETCORE_ENVIRONMENT can be set to any value, but three values are supported by the framework: Development, Staging, and Production. If ASPNETCORE_ENVIRONMENT isn't set, it will default to Production.

For these three values these appsettings.ASPNETCORE_ENVIRONMENT.json files are supported out of the box - appsettings.Staging.json, appsettings.Development.json and appsettings.Production.json

The above three application setting json files can be used to configure multiple environments.

Example - appsettings.Staging.json

{
    "Logging": {
        "IncludeScopes": false,
        "LogLevel": {
            "System": "Information",
            "Microsoft": "Information"
        }
    },
    "MyConfig": "My Config Value for staging."
}

Use Configuration["config_var"] to retrieve any configuration value.

public class Startup
{
    public Startup(IHostingEnvironment env, IConfiguration config)
    {
        Environment = env;
        Configuration = config;
        var myconfig = Configuration["MyConfig"];
    }

    public IConfiguration Configuration { get; }
    public IHostingEnvironment Environment { get; }
}

@Arthur Attout 2018-04-17 06:44:32

What about nested objects ?

@WeHaveCookies 2018-05-15 22:11:32

Nested objects can be obtained with Configuration["MyConfig:SomethingNested"]

@Gun5m0k3 2019-04-03 03:56:35

As can be seen in the file github.com/aspnet/AspNetCore/blob/master/src/DefaultBuilder/‌​src/… at line 167 ASP.NET Core currently loads appsettings.json + appsettings.{env.EnvironmentName}.json. So the statement that ASP.NET Core only loads Development, Staging and Production appsettings.json files is currently incorrect.

@Toolkit 2019-08-02 10:27:51

so am I supposed to set Windows variable ASPNETCORE_ENVIRONMENT every time? Things were way easier in .Net 4. These JSON fanatics did screw it up big time

@Aseem Gautam 2019-08-02 10:31:07

@Toolkit You can set the environment variable globally. docs.microsoft.com/en-us/aspnet/core/fundamentals/…

@harveyt 2018-10-26 16:02:49

I guess the simplest way is by DI. An example of reaching into Controller.

// StartUp.cs
public void ConfigureServices(IServiceCollection services)
{
    ...
    // for get appsettings from anywhere
    services.AddSingleton(Configuration);
}

public class ContactUsController : Controller
{
    readonly IConfiguration _configuration;

    public ContactUsController(
        IConfiguration configuration)
    {
        _configuration = configuration;

        // sample:
        var apiKey = _configuration.GetValue<string>("SendGrid:CAAO");
        ...
    }
}

@harveyt 2018-10-26 16:10:22

Reading the other answers, this should be the best.

@shajji 2018-08-10 06:59:42

Just create An AnyName.cs file and paste following code.

using System;
using System.IO;
using Microsoft.Extensions.Configuration;

namespace Custom
{
    static class ConfigurationManager
    {
        public static IConfiguration AppSetting { get; }
        static ConfigurationManager()
        {
            AppSetting = new ConfigurationBuilder()
                    .SetBasePath(Directory.GetCurrentDirectory())
                    .AddJsonFile("YouAppSettingFile.json")
                    .Build();
        }
    }
}

Must replace YouAppSettingFile.json file name with your file name.
Your .json file should look like below.

{
    "GrandParent_Key" : {
        "Parent_Key" : {
            "Child_Key" : "value1"
        }
    },
    "Parent_Key" : {
        "Child_Key" : "value2"
    },
    "Child_Key" : "value3"
}

Now you can use it.
Don't forget to Add Reference in your class where you want to use.

using Custom;

Code to retrieve value.

string value1 = ConfigurationManager.AppSetting["GrandParent_Key:Parent_Key:Child_Key"];
string value2 = ConfigurationManager.AppSetting["Parent_Key:Child_Key"];
string value3 = ConfigurationManager.AppSetting["Child_Key"];

@shajji 2018-08-10 07:17:42

Thnx for formattng :) Daniel Puiu

Related Questions

Sponsored Content

28 Answered Questions

[SOLVED] Get int value from enum in C#

  • 2009-06-03 06:46:39
  • jim
  • 1368530 View
  • 1649 Score
  • 28 Answer
  • Tags:   c# enums casting int

39 Answered Questions

21 Answered Questions

[SOLVED] How do you give a C# Auto-Property a default value?

2 Answered Questions

8 Answered Questions

[SOLVED] .Net Core Unit Testing - Mock IOptions<T>

6 Answered Questions

[SOLVED] custom keys in appSettings.json not working in ASP.NET Core 2.0

2 Answered Questions

3 Answered Questions

2 Answered Questions

[SOLVED] Unable to find Use.RunTimePageInfo() method in startup.cs file in aspnet core

  • 2016-07-03 10:46:25
  • user1744973
  • 2516 View
  • 8 Score
  • 2 Answer
  • Tags:   c# asp.net .net

1 Answered Questions

Sponsored Content