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<Startup>();
                });
    }

新建一個名為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<int>("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文件。
image

讀取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<Startup>();
                });
    }

新建一個名為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<int>("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文件。
image

讀取XML文件

新建ASP.NET Core Web API項目,在主目錄下添加MyXMLConfig.xml文件。

<?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>

在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<Startup>();
                });
    }

新建一個名為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<int>("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文件的配置。
image

讀取配置項的方法

說幾個在讀取配置項中比較常用的方法,大家可以根據上面例子,自己試一下,這里就不詳細講解了。

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<Startup>();
                });
    }

新建一個名為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<Model>();
            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的配置。
image

自定義配置

如果上面的方式還不能滿足項目要求的話,還可以從數據庫中讀取配置信息。接下來我們通過實體框架(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<EFModel> Values { get; set; }
    }

創建用於實現 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);
        }
    }

通過從 ConfigurationProvider 繼承來創建自定義配置提供程序。 當數據庫為空時,配置提供程序將對其進行初始化。

    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;
        }
    }

使用 AddEFConfiguration 擴展方法將配置源添加到 ConfigurationBuilder。

    public static class EFExtensions
    {
        public static IConfigurationBuilder AddEFConfiguration(this IConfigurationBuilder builder,Action<DbContextOptionsBuilder> 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>();
                });
    }

在Startup中通過依賴注入添加據庫上下文服務,向控制器提供服務。

    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();
            });
        }
    }

在控制器中注入服務,讀取內存數據庫中的數據。

    [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;
        }
    }

利用PostMan可以看到已經讀取到我們自定義的配置源。
image
加一張整體的項目結構,方便大家理解。
image
最近疫情有些反復,出門做好個人防護,玩耍時別忘記學習。最后祝大家周末愉快!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM