Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
West Wind WebSurge - Rest Client and Http Load Testing for Windows

Strongly Typed Configuration Settings in ASP.NET Core


:P
On this page:

One of the first things I do whenever I start on a new project is to set up project level configuration. So it's no surprise as I'm starting to finally dig back into ASP.NET Core after the big re-org, the first thing I started with was configuration. Things have changed a bit since the last time I wrote about this subject (post forwarded to this one now) and things have thankfully gotten a little easier.

Pluggable Configuration

ASP.NET Core has a pluggable configuration system which supports a variety of different mechanisms for reading configuration data. It looks like it still doesn't support a way to write configuration data, but that's a topic for another day. In this post I'll talk specifically about adding strongly typed configuration values to your configuration using the built-in configuration providers - IOptions<T> in particular.

Add references

The first thing in adding strongly typed configuration is to add an additional configuration package that provides the support for strongly typed configuration classes.

The relevant package is Microsoft.Extensions.Options.ConfigurationExtensions added on the bottom in project.json:

{
  "dependencies": {
    "Microsoft.NETCore.App": {
      "version": "1.0.0-rc2-3002702",
      "type": "platform"
    },
    "Microsoft.AspNetCore.Mvc": "1.0.0-rc2-final",
    "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0-rc2-final",
    "Microsoft.AspNetCore.Server.Kestrel": "1.0.0-rc2-final",
    "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0-rc2-final",
    "Microsoft.Extensions.Configuration.FileExtensions": "1.0.0-rc2-final",
    "Microsoft.Extensions.Configuration.Json": "1.0.0-rc2-final",
    "Microsoft.Extensions.Logging": "1.0.0-rc2-final",
    "Microsoft.Extensions.Logging.Console": "1.0.0-rc2-final",
    "Microsoft.Extensions.Logging.Debug": "1.0.0-rc2-final",
    "Microsoft.AspNetCore.StaticFiles": "1.0.0-rc2-final",
    "Microsoft.AspNetCore.Diagnostics": "1.0.0-rc2-final",
    
    
    "Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0-rc2-final",
  },
  ...
}

The configuration extensions give you access to the required Configuration overload to map a strongly typed class to a configuration section in the configuration store.

Create a new Configuration Class

Next create a new class that will hold your configuration settings. The class can be a simple POCO class:

public class MySettings
{
    public string ApplicationName { get; set; } = "My Great Application";
    public int MaxItemsPerList { get; set; } = 15;
}

This is very simple example, but the class you create can be more complex, with nested properties and even lists and collection.

Hooking up the Configuration

Next we need to configure the Dependency Inject and register the new configuration class so it can map the configuration data to the actual POCO object.

Here's what you need for the strongly typed class to become available as a configuration object.

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    // Add functionality to inject IOptions<T>
    services.AddOptions();
    
    // Add our Config object so it can be injected
    services.Configure<MySettings>(Configuration.GetSection("MySettings"));
    
    // *If* you need access to generic IConfiguration this is **required**
    services.AddSingleton<IConfiguration>(Configuration);
}

AddOptions() adds the basic support for injecting IOptions<T> based objects into your code filled with the configuration data from the store. You then register your actual configuration class and map it to the configuration section it should use to read the data from.

In this context a section of a JSON configuration file is a top level property as you'll see in the next step. In Environment variables a section would be separator level based on the separator character (: or __).

Injecting IConfiguration

This is unrelated to using the strongly typed class and IOptions, but when you need inject a more generic IConfiguration for using string based configuration, make sure to explicitly register IConfiguration with the DI system. If you don't you get this error:

InvalidOperationException: Unable to resolve service for type 'Microsoft.Extensions.Configuration.IConfiguration' while attempting to activate 'WebApplication8.Controllers.ConfigurationController'.

Adding services.AddSingleton<IConfiguration>(Configuration) fixes this issue.

Adding configuration values to Appsettings.json

Let's assume you use the default configuration that gets set up in a new project like this:

public Startup(IHostingEnvironment env)
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
        .AddEnvironmentVariables();
        
    Configuration = builder.Build();
}

This results in configuration settings being stored in appsettings.json with potential override files for a the given environment (ie. appsettings.production.json).

You can now add your custom options below the root as a nested object in appsettings.json:

{
  "MySettings": {
    "ApplicationName": "My Very First MVC Application",
    "MaxItemsPerList": 10
  },  
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  }
}

As mentioned in the previous setting, the name you specify in GetSection("MySettings") maps to a top level property in the JSON file. Anything below is pulled into your configuration object when the configuration is read.

Accessing the Strongly Typed Configuration in an MVC Controller

In order to use the newly created configuration section we now have to inject the configuration data into the controller. There are a couple of ways to get at the configuration data:

  • Using the IOptions strongly typed object
  • IConfiguration.GetValue()

Let's look at the strongly typed resources first.

[Route("api")]
public class ConfigurationController : Controller
{
    private MySettings MySettings { get; set; }

    public ConfigurationController(IOptions<MySettings> settings)
    {            
        MySettings = settings.Value;
    }
           

    [HttpGet("appname")]
    public string AppName()
    {
        return MySettings.ApplicationName;
    }

    [HttpGet("maxlistcount")]
    public int MaxListCount()
    {
        return MySettings.MaxItemsPerList;
    }
}    

Start by creating a constructor that injects IOptions<MySettings> which gives you the the configured MySettings object via the .Value property and store it in a private property.

In the actual controller methods you can now access the configuration object using simple strongly typed property values as you'd expect.

Nice!

Using String Configuration Values

You can also access your the configuration data directly using string identification without the strongly typed object, by using the IConfiguration provider.

Plain IConfiguration access can be useful if you just want to add values to your configuration file without explicitly creating a mapping object and if you need to reload your configuration without restarting.

To do this add a Configuration property and pass an IConfiguration instance into the Controller's constructor:

[Route("api")]
public class ConfigurationController : Controller
{

    private IConfiguration Configuration { get; set; }
    private MySettings MySettings { get; set; }

    public ConfigurationController(IOptions<MySettings> settings, IConfiguration configuration)
    {            
        MySettings = settings.Value;
        Configuration = configuration;
    }
           

    [HttpGet("appname")]
    public string AppName()
    {
        return MySettings.ApplicationName;
    }

    [HttpGet("maxlistcount")]
    public int MaxListCount()
    {
        return MySettings.MaxItemsPerList;
    }


    [HttpGet("appname_key")]
    public string AppNameKey()
    {
        return Configuration.GetValue<string>("MySettings:ApplicationName");            
    }

    [HttpGet("maxlistcount_key")]
    public int MaxListCountKey()
    {
        return Configuration.GetValue<int>("MySettings:MaxItemsPerList");
    }
}

Refreshing Configuration Values

Unlike standard ASP.NET applications, ASP.NET Core applications don't automatically refresh the configuration data when the data is changed in the configuration store.

This means if you make a change while the application is running, you either need to restart the application, or explicitly refresh the configuration values.

However, the Configuration API does includes a IConfigurationRoot::Refresh() method that can be called and this works to refresh values if the source can refresh these values.

You can add this method somewhere in your Admin API if and invoke it when you make changes through a Web interface for example.

To use the Reload() functionality:

Add Configuration

In the ConfigureServices() method add:

services.AddSingleton<IConfigurationRoot>(Configuration);   // IConfigurationRoot
services.AddSingleton<IConfiguration>(Configuration);   // IConfiguration explicitly

to add allow IConfigurationRoot to be injectable. Next you need to add it to the control to be actually injected:

private IConfiguration Configuration { get; set; }
private MySettings MySettings { get; set; }
private IConfigurationRoot ConfigRoot { get; set; }

public ConfigurationController(IOptions<MySettings> settings, IConfiguration configuration,IConfigurationRoot configRoot)
{            
    MySettings = settings.Value;
    Configuration = configuration;
    
    ConfigRoot = configRoot;
}

And finally you can access the config root somewhere in your controller:

[HttpGet("reloadconfig")]
public ActionResult ReloadConfig()
{
    ConfigRoot.Reload();

    // this should give the latest value from config
    var lastVal = Configuration.GetValue<string>("MySettings:ApplicationName");
    
    return Ok(lastVal); 
}

This works to refresh the string based configuration value access via IConfiguration.

Unfortunately it does not work for the strongly typed value because that value is read on startup, stored and then not updated again. So the following will not refresh:

var lastVal = Mysettings.ApplicationName;
return Ok(lastVal); 

I haven't found a good way to do a refresh the strongly typed value short of a stop/start cycle for the application.

Summary

ASP.NET Core finally bakes in support for strongly typed configuration objects, which is nice as it removes the need to rely on a separate solution for this functionality as I had been doing (using my Westwind.Configuration library). The native support doesn't provide all of those features - specifically no support for writing and reliably reloading the config store - but it does provide the strong typing and relatively easy way to use different, pluggable providers which is good enough for more most applications.

I use strongly typed configuration extensively in every application, and I'm glad to see this functionality baked in natively. The easier it is to access configuration values, the more likely it is you end up building a configurable application. Go (con)figure...

Posted in ASP.NET  C#  ASP.NET  

The Voices of Reason


 

Andrew Lock
May 23, 2016

# re: Strongly Typed Configuration Settings in ASP.NET Core

Nice post! Particularly useful point about injecting the IConfiguration. I actually wrote a similar post the other day and missed that as a possibility to access the raw configuration.

I was more focused on the properties of your strongly typed configuration models that don't bind correctly : http://andrewlock.net/how-to-use-the-ioptions-pattern-for-configuration-in-asp-net-core-rc2/

It's interesting that the settings don't refresh automatically - my understanding of the 'reloadOnChange' parameter of AddJsonFile() was that it would do just that! Is that not the case? Or is it just that that only works for this particular FileProvider rather than the whole configuration in general.

Again, great post!

Rick Strahl
May 23, 2016

# re: Strongly Typed Configuration Settings in ASP.NET Core

@Andrew - "reloadOnChange" is not working for me. I haven't checked closely in what scenarios it might work - it's not working when running through IIS express at least.

IConfiguration injection - yeah I had a back and forth on that with David Fowler yesterday. It seems odd to me that this is not available by default without having to explicitly add it to the DI provider. Seems like a pretty crucial component you'd need just about anywhere in the application if you're managing configuration correctly. Oddly IOptions<T> doesn't need anything and it probably depends on IConfiguration to read that data - yet still it's not injectable by default unless you explicitly add it.

The problem I have with that is that if you have sub-components that may depend on configuration, you are dependent on developers explicitly adding IConfiguration somewhere in their service config. If they don't - a sub-component can't get at IConfiguration cause it's simply not registered which is a real sucky situation IMHO.

Andrew Lock
May 23, 2016

# re: Strongly Typed Configuration Settings in ASP.NET Core

@Rick - yeah I agree RE developers needing to explicitly add the IConfiguration, though I guess it's an attempt to drive all access to configuration through strongly typed config classes?

There appear to be a lot of closed issues relating to reloadChanges not working properly cross platform and so being removed, but I haven't dug in to what the state of play is now. Maybe was too difficult to do reliably cross platform so was pulled out, so maybe that overload will disappear too..

KRDM
May 25, 2016

# re: Strongly Typed Configuration Settings in ASP.NET Core

Saved my bacon. Been fighting this for a few days now. Thanks!

Mike-EEE
June 09, 2016

# re: Strongly Typed Configuration Settings in ASP.NET Core

SO GREAT to see the thinking here in getting a more POCO-based approach to configuration. As great as project.json was, it was rooted in the friction and error-prone approach that both .NET Configuration and MSBuild suffer from: document-model-mapping-to-POCO, which creates unnecessary artifacts and makes it more difficult for tooling (and thus the end developer).

There are a few open GitHub issues/discussions that are taking place to move MSBuild and the new Roslyn-based project system to a new POCO-based model. It would be AWESOME to get your feedback and/or support here:
https://github.com/Microsoft/msbuild/issues/613
https://github.com/dotnet/roslyn-project-system/issues/37

Thank you for any consideration and support -- and for making this great article!

Raman
June 11, 2016

# re: Strongly Typed Configuration Settings in ASP.NET Core

Can you please provide some scenarios on how you use strongly typed configuration in your application?

Rick Strahl
June 11, 2016

# re: Strongly Typed Configuration Settings in ASP.NET Core

@Raman - everywhere! Anything that's configurable in my application I tend to store in a configuration setting. ConnectionStrings, Folder locations, Operational Options, defaults etc.

Thanh
June 23, 2016

# re: Strongly Typed Configuration Settings in ASP.NET Core

Hi Rick,

I try this on RC 2 and it does not recognise Configuration in the following statement, what packages or namespace needed to be added?

// Add our Config object so it can be injected
    services.Configure<MySettings>(Configuration.GetSection("MySettings"));


Thanks

Rick Strahl
June 23, 2016

# re: Strongly Typed Configuration Settings in ASP.NET Core

Uhm did you read the post? Microsoft.Extensions.Options.ConfigurationExtensions

Andrew Lock
June 23, 2016

# re: Strongly Typed Configuration Settings in ASP.NET Core

@Rick - I finally got round to looking in to the 'reloadOnChange' aspect of the configuration files - it turns out this does work, it's just rather obfuscated! I wrote a post on it here: http://andrewlock.net/reloading-strongly-typed-options-when-appsettings-change-in-asp-net-core-rc2/.

The tl;dr; version is that 'reloadOnChange' does seem to work to reload the raw IConfigurationRoot. In order to reload Options, you need to inject IOptionsMonitor<T> instead of IOptions<T>, and register a callback on the IOptionsMonitor<> you want to reloaded with config changes.

Unfortunately, while this works on RC2, it has since been removed, but will be back post 1.0!

Vitaliy
July 07, 2016

# re: Strongly Typed Configuration Settings in ASP.NET Core

Hello, @Rick. You can look at my solution for autoreload strongly typed configuration at http://net-nts.blogspot.ru/2016/07/autoreload-strongly-typed-configuration.html

Giuseppe
July 08, 2016

# re: Strongly Typed Configuration Settings in ASP.NET Core

Hi all, @Rick. Your implementation from this post used to work in my team project on RC1. Now we're migrating to RTM and we find the following issue: 'configuration.GetSection("someTopLevelKey")' returns null. When I try 'configuration.GetKey("someTopLevelKey:propertyKey")' the value is returned, so configuration source are set correctly (thanks to 'SetBasePath()' too).

Besided that method, there used to be also a 'configuration.Get<SomeConfigClass>("someTopLevelKey")' which is not there anymore. We tried replacing with 'GetValue<>()' and it returns null as well.

Does anyone know how to grab a whole section of e.g. appsetting.json, and map it to correspondent strongly-typed POCO configuration class?

TA

Sapan Desai
July 12, 2016

# re: Strongly Typed Configuration Settings in ASP.NET Core

Hi Rick, Nice post. Thanks. I am wondering how I could make use of this feature in my unit / integration tests where there is NO application Startup.cs. One way that I am trying to do is as follows (below code is straight out of one of the unit / integration test methods):

var settings = Options.Create(new ProductApiSettings());
var productAPIUrl = settings.Value.ApiUri;

But during the test execution, when I look at the value of "productAPIUrl", it is still null. Even though I have an appsettings.json file as follows:

{
"ApiUri": "http://<<productAPI URL>>"
}

Chris
July 31, 2016

# re: Strongly Typed Configuration Settings in ASP.NET Core

Hi Rick

Thanks for all these articles, really useful.

Re: the strongly typed object ("MySettings" in your example above) and it not updating automatically....

I have done a couple of quick tests in the Azure App Service. In the Azure Portal under application settings I added the setting key (e.g. MySettings:ApplicationName in your example). When the settings are saved in the portal, it appears that the application is restarted. Therefore, both mechanisms for getting the setting values (i.e. strongly typed object and string config) will give the updated values.

Chris

Uli Weltersbach
August 17, 2016

# re: Strongly Typed Configuration Settings in ASP.NET Core

Hi Rick,

I'm having the same issue as Raman:
The namespace "Microsoft.Extensions.Options.ConfigurationExtensions" doesn't exist in Core 1.0.0 and hence there's no method signature that allows me to call "services.Configure<MySettings>(Configuration.GetSection("MySettings"));"
Could you explain exactly which package you get "Microsoft.Extensions.Options.ConfigurationExtensions" and the extension method from?
Is it really still the same (I just recently upgraded to Core 1.0.0 so I might be missing something)?

// Uli

Andrew
August 18, 2016

# re: Strongly Typed Configuration Settings in ASP.NET Core

Hi @Guiseppe,

You can load it in to the configuration class like so:

var config = new Settings();
Configuration.GetSection("Settings").Bind(config);


I use this approach to inject the configuration class directly in to my IOC container in order to avoid the IOptions<> cruft

mejobloggs
September 17, 2016

# re: Strongly Typed Configuration Settings in ASP.NET Core

Can I access MySettings from a razor file?

I'm used to having MySettings as a static class and been able to access it anywhere by doing MySettings.MyValue

Can't figure out how to use the method in this tutorial in a razor view

Blake
October 12, 2016

# re: Strongly Typed Configuration Settings in ASP.NET Core

You really missed the boat on a very important bit of documentation:

Within your controller, you need to add the following Using statement:

using Microsoft.Extensions.Options;

Rick Strahl
October 12, 2016

# re: Strongly Typed Configuration Settings in ASP.NET Core

@Blake - yeah - getting the right package references is probably the most painful thing about ASP.NET Core for me. Since most things are extension methods they are not easily discoverable, and it just looks like this stuff isn't there. Relying so heavily on extension methods is a Design flaw IMHO.

Nigel Belham
November 21, 2016

# re: Strongly Typed Configuration Settings in ASP.NET Core

Hi Rick. RE "Adding services.AddSingleton(Configuration) fixes this issue."

Using ASP.NET Core I found that I had to specify the IConfigurationRoot Interface.

services.AddSingleton(Configuration); Which can be simplified to... services.AddSingleton(Configuration); Hope this helps.

Richard
November 25, 2016

# re: Strongly Typed Configuration Settings in ASP.NET Core

How do we enable an injection of the option setting object to a data access layer in a separate project, without using IOption<>?


Wade
December 31, 2016

# re: Strongly Typed Configuration Settings in ASP.NET Core

I noticed a few people talking about hot loading/hot swapping configs in the comments section. Essentially the IOptionsMonitor interface got added, removed, then readded so you can still use this way but it requires a bit of code to get going. Microsoft have also added the IOptionsSnapshot interface though, and this is how they recommend doing reloadable configuration. Instead of injecting IOptions into your class, you now inject IOptionsSnapshot and it will inject the latest settings (At time of instantiation).

That last part is important as if you have a singleton class, the settings won't be "hot swapped" inside it. It's only when the class is built and IOptionsSnapshot is requested from the services collection will it then get the "latest". I wrote a bit about it here : http://dotnetcoretutorials.com/2017/01/01/hot-swapping-custom-configurations-asp-net-core-using-ioptionssnapshot/


Sean Fackrell
April 23, 2017

# re: Strongly Typed Configuration Settings in ASP.NET Core

In case anyone stumbles on this one. You can't use 'IEnumerable' or 'IList' in your config POCO as you can with normal JSON deserialization. If you do, you'll get an InvalidOperation exception when you resolve IOptions. You have to use List instead or presumably a type that can be constructed. i.e.

// This works
public class AppSettings
{
    public List<ApplicationUser> SeedUsers { get; set; }
}

but

// This doesn't
public class AppSettings
{
    public IEnumerable<ApplicationUser> SeedUsers { get; set; }
}

This was using configuration with dependency injection a la

services.Configure<AppSettings>(Configuration);
services.Configure<AppSettings>(Configuration.GetSection(nameof(AppSettings)));

// and then resolved later by the IoC container
IOptions<AppSettings> _settings

with JSON

{
  "AppSettings": {
    "SeedUsers": [
      {
        "UserName": "user1",
        "Email": "user1@gmail.com"
      },
      {
        "UserName": "user2",
        "Email": "user2@gmail.com"
      }
    ]
  }
  }


Gaz
June 19, 2017

# re: Strongly Typed Configuration Settings in ASP.NET Core

Thanks for the article Rick. I've been looking to experiment with Core, but I'm used to code separation and class libraries for my data and logic where possible. In practice, this is great for sharing my libraries between multiple websites and services.

This would mean that my data context would sit in a class library, but the way the Core application settings work makes it quite difficult (or code heavy) to actually use the settings from my web application in the class library.

So far, passing through the settings from the web application to the class library on each method is the only way I've got it to work. It seems so much more work and complexity than the machine/web/app.config hierarchy.

Have you found a good way of actually using a class library that accesses properties of the application config (e.g. the ConnectionStrings)?


Kevin
June 19, 2017

# re: Strongly Typed Configuration Settings in ASP.NET Core

Let's say I store my connection string in this appsettings.json file. What's the best way to access it via a data access class? I can easily retrieve the value in a Controller, but then do I have pass the configuration object to every class the controller uses so it can use the connection string to access data?

Thanks, Kevin


Rick Strahl
June 19, 2017

# re: Strongly Typed Configuration Settings in ASP.NET Core

@Gaz - also struggling with this. The only way to really make this work is DI (ie. expose your component as DI provider accessible for the main app) or alternately rely on static vars to push the data through the application. Realistically the latter is basically what we do in classic .NET apps - the difference is that the configuration system was always there and it's not in .NET core until you startup DI and the rest of the .NET Core infrastructure.

If you ask me - this is a serious design flaw but it is what is. It's easier to use in the most common use cases - it's just a clusterfuck if you have generic .NET (not ASP.NET) components that depend on configuration.

The other problem is that the default DI container is dependent on ASP.NET - so if you want to use DI outside of ASP.NET in a standalone component you have to use a different DI container.

I've been thinking about creating a wrapper around configuration that makes that easier.


Stefano
June 30, 2017

# re: Strongly Typed Configuration Settings in ASP.NET Core

What about strongly typed configuration in a multi tenant web application?

Suppose you have a generic platform config file and than you have a specific file per tenant with some override.

As I undedstood configuration are loaded on application start and stored at application level, am I wrong? So that means integrated configuration is not suitable for this scenario, or there is a way for dealing with it?

Thank you for any suggestion.


Rick Strahl
June 30, 2017

# re: Strongly Typed Configuration Settings in ASP.NET Core

@Stefano - that's the way configuration in .NET has always worked really if you think about it. In full framework it was a static interface (ConfigurationManager. typically) and it's the same here.

Personally I think there are two kinds of configuration: System configuration and Application Configuration. The built-in configuration systems really address System configuration - that are essentially global settings. Application Configuration is specific to an application and that is often more dynamic.

In my apps I tend to separate those out as separate configuration objects. And in a multi-tenant app I think the data would be much better off stored in some sort of data store like a DB table. This sort of thing is best abstracted with something a little more high level than these simple property mappers. In the past I used Westwind.Utilities.Configuration for that, but you certainly can bake configuration directly into your application's domain model in a multi-tenant app.


Matthew Blott
October 10, 2017

# re: Strongly Typed Configuration Settings in ASP.NET Core

Good blog post - I bookmarked it and keep referring to it. The reason for the comment is I've been playing around with appsettings and trying various configurations for production. Anyhow, by chance I found out appsettings.json is automatically loaded, I'm not sure many people are aware of this. I was playing with an example similar to the one above here and added some settings in the json file and called them from an API expecting an error to be thrown and to my surprise they were read correctly. I then dug a bit deeper and found 5 configuration providers are automatically loaded (the following was in the VS Code terminal) ...

Providers [IEnumerable]:Count = 5

[0] [IConfigurationProvider]:Microsoft.Extensions.Configuration.Memory.MemoryConfigurationProvider}

[1] [IConfigurationProvider]:Microsoft.Extensions.Configuration.Json.JsonConfigurationProvider}

[2] [IConfigurationProvider]:Microsoft.Extensions.Configuration.Json.JsonConfigurationProvider}

[3] [IConfigurationProvider]:Microsoft.Extensions.Configuration.EnvironmentVariables.EnvironmentVariablesConfigurationProv ider}

[4] [IConfigurationProvider]:Microsoft.Extensions.Configuration.CommandLine.CommandLineConfigurationProvider}

This is all a bit weird. I thought ASP.NET Core was only supposed to use what you specified ( unless these are what you might call 'sensible defaults').


Rick Strahl
October 14, 2017

# re: Strongly Typed Configuration Settings in ASP.NET Core

@Matthew - I think this is new with ASP.NET Core 2.0 and the new default configuration defaults that it loads. In 2.0 they use common presets and adding configuration providers is one of the things that are set up by default. You can still do things manually if you prefer or remove providers during Configure() cycle.


Triwaters
November 03, 2017

# re: Strongly Typed Configuration Settings in ASP.NET Core

Thank you, Rick, for laying out such a nice explanation for the differences (and relative strengths and weakness) involved between IOptions and IConfiguration. I find once again that a few well-beaten (if not all) paths lead to your blog.


Mario
November 07, 2017

# re: Strongly Typed Configuration Settings in ASP.NET Core

Hi Rick, I have the same question as Kevin. I understand that I can access the appsettings in the controller and view, but how do I access appsettings in the models? Do I have to just pass the configuration settings from the controller to my models everytime?

public IActionResult Index(int id)
{
   Person model = new Person(id); // <-- How do I pass appsetting in here?
   return View(model);
}

In this example, the person model would retrieve a user from SQL based on ID so I would like to pass in the connection string from appsettings.


Rick Strahl
November 07, 2017

# re: Strongly Typed Configuration Settings in ASP.NET Core

Either use DI or use a static object. The documentation has examples how to set up the singleton during application startup.

To use it then:

MyAppConfiguration.Current.SomeSettingsValue

Personally I prefer a static singleton that lives in the business layer for this and is available anywhere in the application, but you can accomplish the same with DI.


Keith Culpepper
January 28, 2018

# re: Strongly Typed Configuration Settings in ASP.NET Core

Unbelievable Rick! I struggled with the injection part of this for hours until I ran across your article. You are without a doubt a life saver!!!! Thanks so much!


mark
October 03, 2018

# re: Strongly Typed Configuration Settings in ASP.NET Core

If I am not using the repo pattern, is the another way/best practice to pass the config/app settings to my datalayer? Currently my dbstring is in the data layer in a class, but I want to move it to appSettings or somewhere else(encrypted of course). Just not sure how to get it down to my data layer from the controller without passing it in the method call or injecting it somehow? Thanks and nice article. I guess I will use the repo pattern next time, ugh...


Rick Strahl
October 04, 2018

# re: Strongly Typed Configuration Settings in ASP.NET Core

Not sure what you mean by Repo pattern. You mean Dependency Injection?

If you don't want to use that you can have a static property on your data layer that you can populate during initialization of the application. Just set the static property and then you have it anywhere.

I tend to do that myself because like you I have some components that may not be part of DI and a static is easy to hold this stuff with in lieu of DI on the few occasions where it's not available.


Ashok
October 04, 2018

# re: Strongly Typed Configuration Settings in ASP.NET Core

Hi Rick,

Very nice and useful article. I spent two weekends in figuring out why IEmailSender is not getting initialized properly. Finally I stumbled upon your article and got clarity on how configurations are getting injected in ASP.Net Core 2.

Keep up the good work 😃

Cheers, Ashok


granadaCoder
November 16, 2018

# re: Strongly Typed Configuration Settings in ASP.NET Core

Thanks @Sean Fackrell. That is the "collection" example and magic syntax sugar (the "List" comment) that I needed. Thanks Ricks for the post.


Bishal Adhikary
December 06, 2018

# re: Strongly Typed Configuration Settings in ASP.NET Core

Awesome post! I am working on my ASP.NET core based project and have been feeling a little uncomfortable using appsettings.json. I am still not sure if appsettings.json gets parsed at runtime or compile time which is why I have been hardcoding some of the more frequently used settings directly in the methods(I definitely would not prefer it parsing the JSON at runtime). Will give your appraoch a try.


Simon
February 14, 2019

# re: Strongly Typed Configuration Settings in ASP.NET Core

Great Post! I especially like the way you can .Configure(..GetSection(..)) to automatically create strongly typed settings object without any mapping code, but I have one question...

What if there is no section? no json settings? what if the data you want has been added to IConfiguration using AddCommandLine() or AddEnvironmentVariables()?


Rick Strahl
February 14, 2019

# re: Strongly Typed Configuration Settings in ASP.NET Core

@Simon - Section doesn't refer to the Json section, but to the structure of the configuration layout. That layout can be created with any of the added providers (ie. Json, CommandLine, Environment etc.). They all use the same layout format, so you can still use sections with Environment variable or command line arguments by naming them with "database:connectionString" for example, which lets you references the database section.


Kostas
April 01, 2019

# re: Strongly Typed Configuration Settings in ASP.NET Core

So, looking at the framework, I cannot find any way of detecting when the reloadOnChange=true took place. That means that one should recreate his DI-ed services on each request (scoped mode) to keep them up-to-date. Couldn't the configuration root object contain a flag to detect changes (hash maybe)? Or, even better, have a way in the framework to propagate the changes to the dependent services automatically when they occur?


Rick Strahl
April 01, 2019

# re: Strongly Typed Configuration Settings in ASP.NET Core

@Kostas - Depends on where you store changes. If you're using a Web application and you store changes in config files linked to web.config the app reloads on changes to that file anyway. If that's a concern then that approach still works.

In desktop applications you pretty much are a single user so you know when you make changes to the single configuration instance and those changes are reflected.

IOW, there are a number of ways this works just by default.

It doesn't work if you external files in Web apps (ie. json for example) but then again if you really need that you can use .config files. Also, frankly configuration shouldn't change at runtime and certainly running a file watcher or some other mechanism to track changes would add quite a bit of unwelcome overhead.


Janus Knudsen
May 17, 2019

# re: Strongly Typed Configuration Settings in ASP.NET Core

Old post, but I really don't see the point in using IOptions unless you're developing a library of some sort and then utilize the PostConfig-feature.

Why would we ever rely on injection IOptions? Especially when we just need the value, which we easily and more obviously could get directly from a strong typed/ GetSection.

IMHO The Reload-feature could as easily just be handled by a simple db-setting/ adjust via query string for flexibility, I think this would be more readable and easier to maintain.

Anyway.. it is always nice to have some tools in the box 😃 Have a great day Rick.


Rick Strahl
June 11, 2019

# re: Strongly Typed Configuration Settings in ASP.NET Core

@Janus - As I've stated in the post I don't think I've ever used IOptions - but rather I either inject the actual typed configuration instance, or - more commonly use a static value which is easier and works across components without the gyrations of DI.

Refresh is a difficult thing to do in Web application. If you're scaled across instances/machines, refreshing a single instance isn't enough and that's where IOptions can help. But I'm not sure if that's worth the effort either. The smarter thing would be that if configuration changes the application should just restart - just as it did in class ASP.NET. Configuration changes are usually applied during startup configuration and that code will never re-run unless the app is restarted.


Shweta S
December 18, 2019

# re: Strongly Typed Configuration Settings in ASP.NET Core

Hi Rick, thanks for the amazing article. I have a ConnectionString in the appSettings.json which is encrypted. Now in Startup in ConfigureServices, I'm decrpyting the same but I'm unable to override the encrypted value as I directly fetch the Configuration.GetSection("MySettings") and add it to Options.

// Add functionality to inject IOptions<T>
   services.AddOptions();
    
// Add our Config object so it can be injected
   services.Configure<MySettings>(Configuration.GetSection("MySettings"));

Hence when I try to read the same in the Controller as settings.Value.ConnectionString I get this as encrypted.

How can I override the same in the Startup before adding it to options. Let me know if I should add more details.

Thanks a lot in advance.


Rick Strahl
December 18, 2019

# re: Strongly Typed Configuration Settings in ASP.NET Core

@Shweta - yes you can't 'intercept' the deserialization process as you could before so whatever value you get is what you get from the configuration. However, there are a few things you can do:

  • Post process the value in your ConfigureServices() handler and decode it there (meh)
  • Use a Getter on the ConnectionString property to decode the value on the fly (or once and cache)

Kostas
August 25, 2020

# re: Strongly Typed Configuration Settings in ASP.NET Core

How about mapping complex types. E.g. I would like a way to map a single connection string name to the actual connection string defined to a different configuration section.

class LoggingSettings {
  public ConnectionString {get; private set; } // Map a connection string name to the actual connection string name+value pair here.
}

class ConnectionString {
   public Name { get; private set; }
   public ConnectionStringValue { get; private set; }
}

JSON:

...
"LoggingSettings" : {
   "ConnectionString": "LoggingConnectionString"
},
"ConnectionStrings" : {
   "LoggingConnectionString": "Data Source=..."
},
...

I wish MS made things more flexible and provided examples on complex setups...


Rick Strahl
August 25, 2020

# re: Strongly Typed Configuration Settings in ASP.NET Core

@Costas - sure you can do that. You just use multiple configuration objects. I do this all the time in most of my applications. Rather than have one large configuration object I have several specific ones and I load up each one with what's described here. I can then either collect them all into my own object which can be stored in DI, or you just reference/load them individually.


Frank
August 27, 2021

# re: Strongly Typed Configuration Settings in ASP.NET Core

Searching again on the web for an answer to a question, just as I have been doing for decades, and once again I run into that same old smiley face, Rick Strahl, who now seems so familiar to me it's like meeting an old friend. I might have to take the family on holiday from Europe to Hawaii just to go and see you in person.


jamal kaksouri
September 20, 2021

# re: Strongly Typed Configuration Settings in ASP.NET Core

In startup class using strongly type

usage:

services.Configure<MySettings>(a => Configuration.GetSection(nameof(ConnectionStrings)).Bind(a));

instead of...

services.Configure<MySettings>(Configuration.GetSection("MySettings"));

West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2024