ASP.NET|ASP.NET Core 学习笔记 第四篇 ASP.NET Core 中的配置

前言 说道配置文件,基本大多数软件为了扩展性、灵活性都会涉及到配置文件,比如之前常见的app.config和web.config。然后再说.NET Core,很多都发生了变化。总体的来说技术在进步,新的方式更加轻量级,具有更好的扩展性,数据源更加多样性。
ASP.NET Core 应用可用的配置提供程序

提供程序 一下对象提供配置
Azure Key Vault 配置提供程序 Azure Key Vault
Azure 应用配置提供程序 Azure 应用程序配置
命令行配置提供程序 命令行参数
自定义配置提供程序 自定义源
环境变量配置提供程序 环境变量
文件配置提供程序 INI、JSON 和 XML 文件
Key-per-file 配置提供程序 目录文件
内存配置提供程序 内存中集合
用户机密 用户配置文件目录中的文件
配置提供程序的典型顺序为:
1.appsettings.json
2.appsettings.Environment.json
3.用户机密
4.使用环境变量配置提供程序通过环境变量提供。
5.使用命令行配置提供程序通过命令行参数提供。
注意: 通常的做法是将命令行配置提供程序添加到一系列提供程序的末尾,使命令行参数能够替代由其他提供程序设置的配置。
配置模型三要素 .NET Core的配置系统由三个核心对象构成,分别是IConfiguration、IConfigurationBuilder、IConfigurationSource。
  • IConfiguration:读取出来的配置信息最终会转换成一个IConfiguration对象供应用程序使用。
  • IConfigurationBuilder:IConfigurationBuilder是IConfiguration对象的构建者。
  • IConfigurationSource:则代表配置数据最原始的来源。
文件配置 读取INI文件配置 首先创建一个ASP .NET Core Web API项目,在主目录下添加MyIniConfig.ini文件。
ID=1 Title="INIConfig title" Name="INIConfig name"[Logging:LogLevel] Default=Information

在Program类中读取配置文件
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(); }); }

新建一个名为SettingsController的控制器,读取配置文件。
[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("ID"); var title = Configuration["Title"]; var defaultLogLevel = Configuration["Logging:LogLevel:Default"]; return Content($"ID:{id}\n" +$"Title:{title}\n"+ $"Default Log Level: {defaultLogLevel}"); } }

利用PostMan可以看到已经读取到刚刚设置的INI文件。
ASP.NET|ASP.NET Core 学习笔记 第四篇 ASP.NET Core 中的配置
文章图片

读取Json配置文件。 新建ASP.NET Core Web API项目,在主目录下添加MyJsonConfig.json文件。
{ "ID": "1", "Title": "My JsonConfig", "Logging": { "LogLevel": { "Default": "Information" } } }

在Program类中读取配置文件
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(); }); }

新建一个名为SettingsController的控制器,读取配置文件。
[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("ID"); var title = Configuration["Title"]; var defaultLogLevel = Configuration["Logging:LogLevel:Default"]; return Content($"ID:{id}\n" + $"Title:{title}\n" + $"Default Log Level: {defaultLogLevel}"); } }

利用PostMan可以看到已经读取到刚刚设置的Json文件。
ASP.NET|ASP.NET Core 学习笔记 第四篇 ASP.NET Core 中的配置
文章图片

读取XML文件 新建ASP.NET Core Web API项目,在主目录下添加MyXMLConfig.xml文件。
1 MyXMLConfig Title MyXMLConfig Name Information

在Program类中读取配置文件
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(); }); }

新建一个名为SettingsController的控制器,读取配置文件。
[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("ID"); var title = Configuration["Title"]; var defaultLogLevel = Configuration["Logging:LogLevel:Default"]; return Content($"ID:{id}\n" + $"Title:{title}\n" + $"Default Log Level: {defaultLogLevel}"); } }

利用PostMan可以看到已经读取到XML文件的配置。
ASP.NET|ASP.NET Core 学习笔记 第四篇 ASP.NET Core 中的配置
文章图片

读取配置项的方法 说几个在读取配置项中比较常用的方法,大家可以根据上面例子,自己试一下,这里就不详细讲解了。
GetValue ConfigurationBinder.GetValue 从配置中提取一个具有指定键的值,并将它转换为指定的类型。在上面的中 int id = Configuration.GetValue ("ID"); 就是利用这个方法获取指定类型。
GetSection IConfiguration.GetSection 会返回具有指定子节键的配置子节。
GetChildren IConfiguration.GetChildren 方法获取直接后代配置子节。
Exists ConfigurationExtensions.Exists(IConfigurationSection)确定该部分是否具有 Value 或子级。
将配置绑定到对象 新建ASP.NET Core Web API项目,在主目录下添加MyArray.json文件。
{ "array": { "entries": { "0": "value0", "1": "value1", "2": "value2", "3": "value3" } } }

创建一个model。
public class Model { public string[] Entries { get; set; } }

在Program类中读取配置文件
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(); }); }

新建一个名为SettingsController的控制器,读取配置文件。
[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(); string modelStr = null; for (int j = 0; j < array.Entries.Length; j++) { modelStr += $"Index: {j}Value:{array.Entries[j]} \n"; }return Content(modelStr); } }

利用PostMan可以看到已经读取到绑定到Model的配置。
ASP.NET|ASP.NET Core 学习笔记 第四篇 ASP.NET Core 中的配置
文章图片

自定义配置 如果上面的方式还不能满足项目要求的话,还可以从数据库中读取配置信息。接下来我们通过实体框架(EF)读取数据库中配置信息(埋个伏笔,后续做个相关教程)。便于操作,这次使用内存数据库做配置源。
首先做一个创建一个实体。
public class EFModel { public int ID { get; set; } public string Name { get; set; } public string Value { get; set; } }

添加 EFConfigContext 以存储和访问配置的值。
public class EFConfigContext:DbContext { public EFConfigContext(DbContextOptions options) : base(options) { }public DbSet Values { get; set; } }

创建用于实现 IConfigurationSource 的类。
public class EFConfigurationSource : IConfigurationSource { private readonly Action _optionsAction; public EFConfigurationSource(Action optionsAction) { _optionsAction = optionsAction; }public IConfigurationProvider Build(IConfigurationBuilder builder) { return new EFConfigurationProvider(_optionsAction); } }

通过从 ConfigurationProvider 继承来创建自定义配置提供程序。 当数据库为空时,配置提供程序将对其进行初始化。
public class EFConfigurationProvider:ConfigurationProvider { Action OptionsAction { get; } public EFConfigurationProvider(Action optionsAction) { OptionsAction = optionsAction; }public override void Load() { var builder = new DbContextOptionsBuilder(); OptionsAction(builder); using (var dbContext =new EFConfigContext(builder.Options)) { dbContext.Database.EnsureCreated(); Data =https://www.it610.com/article/!dbContext.Values.Any()?CreateAndSaveValues(dbContext) : dbContext.Values.ToDictionary(c => c.Name, c => c.Value); }}private static IDictionary CreateAndSaveValues(EFConfigContext dbContext) { var configValues = new Dictionary(StringComparer.OrdinalIgnoreCase) { {"name1","value1" }, {"name2","value2" }, {"name3","value3" } }; dbContext.Values.AddRange(configValues.Select(v => new EFModel { Name = v.Key, Value = https://www.it610.com/article/v.Value }).ToArray()); dbContext.SaveChanges(); return configValues; } }

使用 AddEFConfiguration 扩展方法将配置源添加到 ConfigurationBuilder。
public static class EFExtensions { public static IConfigurationBuilder AddEFConfiguration(this IConfigurationBuilder builder,Action optionsAction) { return builder.Add(new EFConfigurationSource(optionsAction)); } }

在 Program.cs 中使用自定义的 EFConfigurationProvider:
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中通过依赖注入添加据库上下文服务,向控制器提供服务。
public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; }public IConfiguration Configuration { get; }public void ConfigureServices(IServiceCollection services) { services.AddDbContext(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(); }); } }

在控制器中注入服务,读取内存数据库中的数据。
[Route("api/[controller]/[action]")] [ApiController] public class SettingsController : ControllerBase {private readonly EFConfigContext _efDbContext; public SettingsController( EFConfigContext efDbContext) { _efDbContext = efDbContext; }public ActionResult> EFSetting() { List list = _efDbContext.Values.ToList(); return list; } }

【ASP.NET|ASP.NET Core 学习笔记 第四篇 ASP.NET Core 中的配置】利用PostMan可以看到已经读取到我们自定义的配置源。
ASP.NET|ASP.NET Core 学习笔记 第四篇 ASP.NET Core 中的配置
文章图片

加一张整体的项目结构,方便大家理解。
ASP.NET|ASP.NET Core 学习笔记 第四篇 ASP.NET Core 中的配置
文章图片

最近疫情有些反复,出门做好个人防护,玩耍时别忘记学习。最后祝大家周末愉快!

    推荐阅读