preface
I've been a little busy recently and I'm a little lazy in my study (ashamed). I take time to learn and finish this blog. I hope to understand. I believe I can stick to it and finish this series. All right, let's do it. When it comes to configuration files, most software will involve configuration files for scalability and flexibility, such as app.config and web.config. Then say. NET Core, many have changed. Generally speaking, technology is progressing, new methods are more lightweight, have better scalability, and data sources are more diverse.
Configuration providers available for ASP.NET Core applications
Provider | The following objects provide configuration |
---|---|
Azure Key Vault configuration provider | Azure Key Vault |
Azure application configuration provider | Azure application configuration |
Command line configuration provider | Command line parameters |
Custom configuration provider | Custom source |
Environment variable configuration provider | environment variable |
Profile provider | INI, JSON, and XML files |
Key per file configuration provider | Catalog file |
Memory configuration provider | In memory collection |
User confidentiality | Files in the user profile directory |
The typical order of configuring providers is:
1.appsettings.json
2.appsettings.Environment.json
3. User confidentiality
4. Use the environment variable configuration provider to provide through the environment variable.
5. Use the command line configuration provider to provide through command line parameters.
Note: it is common practice to add a command line configuration provider to the end of a series of providers so that command line parameters can override the configuration set by other providers.
Three elements of configuration model
The configuration system of. NET Core consists of three core objects: IConfiguration, IConfigurationBuilder and IConfigurationSource.
- IConfiguration: the read configuration information will eventually be converted into an IConfiguration object for use by the application.
- IConfigurationBuilder: IConfigurationBuilder is the builder of IConfiguration objects.
- IConfigurationSource: represents the most original source of configuration data.
File configuration
Read INI file configuration
First, create an ASP. Net core web API project and add the MyIniConfig.ini file in the home directory.
ID=1 Title="INIConfig title" Name="INIConfig name" [Logging:LogLevel] Default=Information
Read the configuration file in the Program class
public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { config.Sources.Clear(); var env = hostingContext.HostingEnvironment; config.AddIniFile("MyIniConfig.ini", optional: true, reloadOnChange: true); config.AddEnvironmentVariables(); if (args != null) { config.AddCommandLine(args); } }) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }); }
Create a new controller named SettingsController and read the configuration file.
[Route("api/[controller]/[action]")] [ApiController] public class SettingsController : ControllerBase { private readonly IConfiguration Configuration; public SettingsController(IConfiguration configuration) { Configuration = configuration; } public ContentResult INISetting() { int id = Configuration.GetValue<int>("ID"); var title = Configuration["Title"]; var defaultLogLevel = Configuration["Logging:LogLevel:Default"]; return Content($"ID:{id}\n" +$"Title:{title}\n"+ $"Default Log Level: {defaultLogLevel}"); } }
Using PostMan, you can see that the INI file just set has been read.
Read the Json configuration file.
Create a new ASP.NET Core Web API project and add the MyJsonConfig.json file in the home directory.
{ "ID": "1", "Title": "My JsonConfig", "Logging": { "LogLevel": { "Default": "Information" } } }
Read the configuration file in the Program class
public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { config.Sources.Clear(); var env = hostingContext.HostingEnvironment; config.AddJsonFile("MyJsonConfig.json", optional: true, reloadOnChange: true); config.AddEnvironmentVariables(); if (args != null) { config.AddCommandLine(args); } }) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }); }
Create a new controller named SettingsController and read the configuration file.
[Route("api/[controller]/[action]")] [ApiController] public class SettingsController : ControllerBase { private readonly IConfiguration Configuration; public SettingsController(IConfiguration configuration) { Configuration = configuration; } public ContentResult JsonSetting() { int id = Configuration.GetValue<int>("ID"); var title = Configuration["Title"]; var defaultLogLevel = Configuration["Logging:LogLevel:Default"]; return Content($"ID:{id}\n" + $"Title:{title}\n" + $"Default Log Level: {defaultLogLevel}"); } }
Using PostMan, you can see that the Json file just set has been read.
Read XML file
Create a new ASP.NET Core Web API project and add MyXMLConfig.xml file in the home directory.
<?xml version="1.0" encoding="utf-8" ?> <configuration> <ID>1</ID> <Title>MyXMLConfig Title</Title> <Name>MyXMLConfig Name</Name> <Logging> <LogLevel> <Default>Information</Default> </LogLevel> </Logging> </configuration>
Read the configuration file in the Program class
public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { config.Sources.Clear(); var env = hostingContext.HostingEnvironment; config.AddXmlFile("MyXMLConfig.xml", optional: true, reloadOnChange: true); config.AddEnvironmentVariables(); if (args != null) { config.AddCommandLine(args); } }) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }); }
Create a new controller named SettingsController and read the configuration file.
[Route("api/[controller]/[action]")] [ApiController] public class SettingsController : ControllerBase { private readonly IConfiguration Configuration; public SettingsController(IConfiguration configuration) { Configuration = configuration; } public ContentResult XmlSetting() { int id = Configuration.GetValue<int>("ID"); var title = Configuration["Title"]; var defaultLogLevel = Configuration["Logging:LogLevel:Default"]; return Content($"ID:{id}\n" + $"Title:{title}\n" + $"Default Log Level: {defaultLogLevel}"); } }
Using PostMan, you can see the configuration of the XML file that has been read.
Method of reading configuration item
Here are some common methods for reading configuration items. You can try them yourself according to the above examples. I won't explain them in detail here.
GetValue
ConfigurationBinder.GetValue extracts a value with the specified key from the configuration and converts it to the specified type. In the above, int id = Configuration.GetValue("ID"); This method is used to obtain the specified type.
GetSection
IConfiguration.GetSection returns the configuration sub section with the specified sub section key.
GetChildren
The IConfiguration.GetChildren method obtains the direct descendant configuration sub section.
Exists
ConfigurationExtensions.Exists(IConfigurationSection) determines whether the section has a Value or child.
Bind configuration to object
Create a new ASP.NET Core Web API project and add the MyArray.json file in the home directory.
{ "array": { "entries": { "0": "value0", "1": "value1", "2": "value2", "3": "value3" } } }
Create a model.
public class Model { public string[] Entries { get; set; } }
Read the configuration file in the Program class
public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { config.Sources.Clear(); var env = hostingContext.HostingEnvironment; config.AddJsonFile("MyArray.json",optional: true,reloadOnChange: true); config.AddEnvironmentVariables(); if (args != null) { config.AddCommandLine(args); } }) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }); }
Create a new controller named SettingsController and read the configuration file.
[Route("api/[controller]/[action]")] [ApiController] public class SettingsController : ControllerBase { private readonly IConfiguration Configuration; public SettingsController(IConfiguration configuration) { Configuration = configuration; } public ContentResult ToModel() { array = Configuration.GetSection("array").Get<Model>(); string modelStr = null; for (int j = 0; j < array.Entries.Length; j++) { modelStr += $"Index: {j} Value: {array.Entries[j]} \n"; } return Content(modelStr); } }
Using PostMan, you can see that the configuration bound to the Model has been read.
Custom configuration
If the above method can not meet the project requirements, you can also read the configuration information from the database. Next, we read the configuration information in the database through the Entity Framework (EF). For ease of operation, the memory database is used as the configuration source this time.
First, create an entity.
public class EFModel { public int ID { get; set; } public string Name { get; set; } public string Value { get; set; } }
Add EFConfigContext to store and access configured values.
public class EFConfigContext:DbContext { public EFConfigContext(DbContextOptions options) : base(options) { } public DbSet<EFModel> Values { get; set; } }
Create a class that implements IConfigurationSource.
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); } }
Create a custom configuration provider by inheriting from the ConfigurationProvider. When the database is empty, the configuration provider initializes it.
public class EFConfigurationProvider:ConfigurationProvider { Action<DbContextOptionsBuilder> OptionsAction { get; } public EFConfigurationProvider(Action<DbContextOptionsBuilder> optionsAction) { OptionsAction = optionsAction; } public override void Load() { var builder = new DbContextOptionsBuilder<EFConfigContext>(); OptionsAction(builder); using (var dbContext =new EFConfigContext(builder.Options)) { dbContext.Database.EnsureCreated(); Data =!dbContext.Values.Any()?CreateAndSaveValues(dbContext) : dbContext.Values.ToDictionary(c => c.Name, c => c.Value); } } private static IDictionary<string, string> CreateAndSaveValues(EFConfigContext dbContext) { var configValues = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) { {"name1","value1" }, {"name2","value2" }, {"name3","value3" } }; dbContext.Values.AddRange(configValues.Select(v => new EFModel { Name = v.Key, Value = v.Value }).ToArray()); dbContext.SaveChanges(); return configValues; } }
Use the AddEFConfiguration extension method to add a configuration source to ConfigurationBuilder.
public static class EFExtensions { public static IConfigurationBuilder AddEFConfiguration(this IConfigurationBuilder builder,Action<DbContextOptionsBuilder> optionsAction) { return builder.Add(new EFConfigurationSource(optionsAction)); } }
Use the custom EFConfigurationProvider in Program.cs:
public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { config.Sources.Clear(); var env = hostingContext.HostingEnvironment; config.AddEFConfiguration( options => options.UseInMemoryDatabase("InMemoryDb")); config.AddEnvironmentVariables(); if (args != null) { config.AddCommandLine(args); } }) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }); }
In Startup, a database context service is added through dependency injection to provide services to the controller.
public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { services.AddDbContext<EFConfigContext>(opt => opt.UseInMemoryDatabase("InMemoryDb")); services.AddControllers(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } }
Inject services into the controller to read the data in the memory database.
[Route("api/[controller]/[action]")] [ApiController] public class SettingsController : ControllerBase { private readonly EFConfigContext _efDbContext; public SettingsController( EFConfigContext efDbContext) { _efDbContext = efDbContext; } public ActionResult<IEnumerable<EFModel>> EFSetting() { List<EFModel> list = _efDbContext.Values.ToList(); return list; } }
Using PostMan, you can see that our customized configuration source has been read.
Add an overall project structure for everyone to understand.
The epidemic situation has been repeated recently. Do a good job in personal protection when you go out and don't forget to learn when you play. Finally, I wish you a happy weekend!