ASP.NET Core

This article is a personal note based on the official documents. Some simple contents are useless. Please refer to the official documents: https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/configuration/?view=aspnetcore-5.0

Configuration is configured using one or more configuration providers. This program reads key value pairs from the following configuration sources. Keys are not case sensitive:

  • Configuration files, such as Appsettings json,MySettings.json, etc. (see the chapter of reading custom configuration file)
  • environment variable
  • Azure Key Vault
  • Azure application configuration
  • Command line parameters
  • Custom Configuration Provider (see the chapter of custom Configuration Provider reading configuration from database)
  • Directory file (see chapter on taking file name and file content as key value pairs)
  • Objects in memory (see configuring memory objects as key value pairs)

1. Default configuration

Host. The createdefaultbuilder method adds configurations in the following order:

  1. ChainedConfigurationProvider: Add Existing IConfiguration as the source.
  2. Use Appsettings json
  3. Use Appsettings {Environment}. json
  4. App secret in Development environment
  5. Environment variables provided by Environment Variables provider
  6. Command line parameters provided by command line provider

If there is a configuration item with the same name, the one added later will replace the one before.

Forcibly convert IConfiguration to IConfigurationRoot, and then traverse its Providers property to view the added configuration items in sequence.

2. Read Appsettings How many methods of configuring items in JSON?

2.1 use index

If the instance of IConfiguration is Configuration, Configuration ["MyKey"] and Configuration["Logging:Loglevel:Default"] can read the matching value.

2.2 using model binding

The official name is options pattern. For ease of understanding, I call it model binding. Add a model class, such as SectionModel:

public class SectionModel
{
    //When binding, only public attributes will be bound, not fields
    public const string SectionName="Position";
    public string Title{get;set;}
    public string Name{get;set;}
}

The corresponding configuration items are:

"Position":{
    "Title":"Editor",
    "Name":"Jos"
}

Then use this:

var model=new SectionModel();
Configuration.GetSection(SectionModel.SectionName).Bind(model);//So you get the configuration
//Of course you can
var model=Configuration.GetSection(SectionModel.SectionName).Get<SectionModel>();

It can also be used in combination with dependency injection:

services.Configure<SectionModel>(Configuration.GetSection(SectionModel.SectionName));
//That's what I wrote when I used it
public class A(IOptions<SectionModel> model)
{
    //model.Title
}

The above usage scenario is Appsettings After the JSON is modified, the new configuration will not be read. If you want to respond to changes in time, change the above IOptions to iopptionssnapshot.

2.3 using getValue < T >

Function: used to obtain the value of a single key value pair.

var number = Configuration.GetValue<int>("NumberKey", 99);//Default 99 if not found

2.4 using GetSection

GetSection(): the returned is also an IConfiguration object, which will never be null. If the specified sectionName does not exist, an empty collection is returned. Therefore, you can still continue to access the return object in the way of 2.1, that is, config["MyKey"]. Usage: GetSection("A"), GetSection("A:B")

2.5 using GetChildren and Exists

GetChildren and Exists are used to judge whether a section Exists, and then obtain the children of the section.

 var selection = Config.GetSection("section2");
 if(selection.Exists())
 {
     var children = selection.GetChildren();
     foreach (var subSection in children)
     {
         //subSection.Key  selection[key]
     }
 }

2.6 differences between ioption < T >, ioptionsnapshot < T > and ioptionmonitor < T >:

  • IOption: it is a singleton, does not support reload (overload when changing), and does not support naming options
  • IOptionSnapshot: scope, reload and naming options
  • IOptionMonitor: singleton, relaod and naming options

About naming options reference https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/configuration/options?view=aspnetcore -5.0#named options support using iconfigurenamedoptions. I don't think they are very useful.

2.7 configure binding validation

You can verify whether the configuration meets the requirements by adding some features such as [Range] and [RegularExpression] to the SectionModel or adding a verification delegate.

see https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/configuration/options?view=aspnetcore-5.0#options-validation

3. Display all configuration items

Traverse iconfiguration AsEnumerable()

4. Read the customized configuration file

You can customize ini, json and xml configuration files. Take json files as an example:

public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                //config.Sources.Clear(); Clear all existing configurations (including appsettings.json configuration)
                config.AddJsonFile("MyConfig.json", 
                    optional: true, //It doesn't matter if the file doesn't exist
                    reloadOnChange: true);
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });

4.1 configure the file name and file content as key value pairs (key per file)

That is, the file name is the key and the content of the file is the value. If the file name is A__B__C. Then the key is A:B:C. Double underscores are replaced by colons.

.ConfigureAppConfiguration((hostingContext, config) =>
{
    var path = Path.Combine(
        Directory.GetCurrentDirectory(), "path/to/files");
    config.AddKeyPerFile(directoryPath: path, optional: true);
})

4.2 configuring objects in memory as key value pairs

Mainly the AddInMemoryCollection method

var Dict = new Dictionary<string, string>
{
    {"MyKey", "Dictionary MyKey Value"},
    {"Position:Title", "Dictionary_Title"},
    {"Position:Name", "Dictionary_Name" },
    {"Logging:LogLevel:Default", "Warning"}
};
        
.ConfigureAppConfiguration((hostingContext, config) =>
{
    config.AddInMemoryCollection(Dict);
})

5. Kestrel endpoint configuration

If in Appsettings JSON is configured with the following Kestrel:Endpoints node, which represents the endpoint node. Any configuration item, regardless of the order, will not overwrite the end node, including UseUrls set in the code, -- urls on the command line and aspnetcore on the environment variable_ urls.

{
  "Kestrel": {
    "Endpoints": {
      "Https": {
        "Url": "https://localhost:9999"
      }
    }
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
} 

6. The custom configuration provider reads the configuration from the database

Demonstrate reading configuration from database with EF. Note: overload when change is not provided

  1. Custom class inherits ConfigurationProvider
public class EFConfigurationProvider : ConfigurationProvider
{
    Action<DbContextOptionsBuilder> OptionsAction { get; }
    public EFConfigurationProvider(Action<DbContextOptionsBuilder> optionsAction)
    {
        OptionsAction = optionsAction;
    }
    public override void Load()
    {
        var builder = new DbContextOptionsBuilder<EFConfigurationContext>();
        OptionsAction(builder);
        using (var dbContext = new EFConfigurationContext(builder.Options))
        {
            dbContext.Database.EnsureCreated();
            Data = dbContext.Values.ToDictionary(c => c.Id, c => c.Value);
        }
    }
}
  1. Custom ConfigurationSource implements IConfiguration interface:
public class EFConfigurationSource : IConfigurationSource
{
    private readonly Action<DbContextOptionsBuilder> _optionsAction;
    public EFConfigurationSource(Action<DbContextOptionsBuilder> optionsAction)
    {
        _optionsAction = optionsAction;
    }
    public IConfigurationProvider Build(IConfigurationBuilder builder)
    {
        return new EFConfigurationProvider(_optionsAction);
    }
}
  1. Then in program CS add
.ConfigureAppConfiguration((hostContext, configBuilder) =>
{
    configBuilder.Add(new EFConfigurationSource(opt=>opt.UseInMemoryDatabase("InMemoryDb")))
})

7. Replace the configuration at runtime

If you feel that some existing configurations do not meet the requirements, you can override these configurations through delegation before the application starts. Then the values you set will be read in the future.

    services.Configure<MyOptions>(myOptions =>
    {
        myOptions.Option1 = "Value configured in delegate";
        myOptions.Option2 = 500;
    });

When the configuration is subsequently read through dependency injection, it will be a new value.

Finally: launchsettings json/launch. JSON configuration is only valid for the development environment and will not be publish ed.

Keywords: ASP.NET dotNETCore

Added by bmcua on Thu, 03 Mar 2022 21:24:01 +0200