Strongly Typed Configuration Settings in ASP.NET Core
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...
The Voices of Reason
# 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/
# 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.
# re: Strongly Typed Configuration Settings in ASP.NET Core
Great Post! I especially like the way you can .Configure
What if there is no section? no json settings? what if the data you want has been added to IConfiguration using AddCommandLine() or AddEnvironmentVariables()?
# 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.
# 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?
# 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.
# 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
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.
# 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.
# 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.
# 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)
# re: Strongly Typed Configuration Settings in ASP.NET Core
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
# re: Strongly Typed Configuration Settings in ASP.NET Core
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!
# re: Strongly Typed Configuration Settings in ASP.NET Core
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.
# re: Strongly Typed Configuration Settings in ASP.NET Core
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..
# re: Strongly Typed Configuration Settings in ASP.NET Core
# re: Strongly Typed Configuration Settings in ASP.NET Core
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!
# re: Strongly Typed Configuration Settings in ASP.NET Core
# re: Strongly Typed Configuration Settings in ASP.NET Core
# re: Strongly Typed Configuration Settings in ASP.NET Core
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
# re: Strongly Typed Configuration Settings in ASP.NET Core
# re: Strongly Typed Configuration Settings in ASP.NET Core
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!
# re: Strongly Typed Configuration Settings in ASP.NET Core
# re: Strongly Typed Configuration Settings in ASP.NET Core
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
# re: Strongly Typed Configuration Settings in ASP.NET Core
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>>"
}
# re: Strongly Typed Configuration Settings in ASP.NET Core
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
# re: Strongly Typed Configuration Settings in ASP.NET Core
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
# re: Strongly Typed Configuration Settings in ASP.NET Core
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
# 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...
# 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.
# re: Strongly Typed Configuration Settings in ASP.NET Core
In case anyone stumbles on this one. You can't use 'IEnumerable
// 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"
}
]
}
}
# 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.
# 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"));
# 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)?
# 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
# 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.
# 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.
# 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.
# re: Strongly Typed Configuration Settings in ASP.NET Core
Within your controller, you need to add the following Using statement:
using Microsoft.Extensions.Options;
# re: Strongly Typed Configuration Settings in ASP.NET Core
# 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').
# 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.
# 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.
# 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.
# 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.
# 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!
# re: Strongly Typed Configuration Settings in ASP.NET Core
Hi Rick. RE "Adding services.AddSingleton
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.
# 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<>?
# 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...
# 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.
# 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
# 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.