首页 > 编程语言 >ASP.NET Core教程-Configuration(配置)- 配置文件

ASP.NET Core教程-Configuration(配置)- 配置文件

时间:2022-10-31 09:00:39浏览次数:42  
标签:Core ASP 配置文件 builder 配置 json Configuration public

更新记录
转载请注明出处:
2022年10月31日 发布。
2022年10月28日 从笔记迁移到博客。

ASP.NET Core应用配置

说明

当我们需要将程序发布到不同环境中时,需要让应用支持配置,以在运行时执行不同的逻辑,例如连接不同环境的数据库、日志的级别开关等。本质上,配置是一种运行时对应用程序行为进行控制的手段。ASP.NET Core通过提供全新的配置组件来提供配置的读取能力,既支持将环境变量、命令行参数、内存字典作为配置数据源,也支持以多种文件格式作为配置数据源,同时提供了轻量级的扩展接口,我们可以非常轻松地定义自己的配置数据源。

ASP.NET Core中的配置与ASP.NET项目中的配置有很大不同,ASP.NET项目使用web.config文件,ASP.NET Core项目使用多种配置源对项目进行配置。ASP.NET Core配置系统支持丰富的配置源,包括文件(json、xml、ini等)、注册表、环境变量、命令行、Azure Key Vault等,还可以配置自定义配置源。可以跟踪配置的改变,可以按照优先级覆盖。

配置组件的核心能力是从各种数据源读取并格式化为Key-Value(键-值)结构。

配置组件的构造过程

配置组件的核心部分包含在下面两个组件包中,与依赖注入组件的模式一样,都是接口实现分离的模式:

Microsoft.Extensions.Configuration.Abstractions
Microsoft.Extensions.Configuration

其中核心的类型接口有:

IConfigurationBuilder,表示配置对象构造者,负责IConfigurationRoot的构造。
IConfigurationSource,表示一个配置数据源。
IConfigurationProvider,表示配置提供程序,负责从数据源读取配置数据并转换为Key-Value结构。
IConfiguration,表示配置对象,抽象为一个Key-Value结构。
IConfigurationRoot,表示配置对象的根,继承自IConfiguration。
IConfigurationSection,表示配置对象的一个节点,继承自IConfiguration。

整个配置组件构建过程:
创建IConfigurationBuilder。
向Builder中添加各种配置源(ConfigurationSource)。
通过Build方法构建IConfigurationRoot对象,其内部过程如下:
由ConfigurationSource的Build方法创建对应的ConfigurationProvider。
将ConfigurationProvider存储在ConfigurationRoot中。

image

ASP.NET Core主要的配置文件

配置文件 描述
Panda.csproj 描述项目信息,比如依赖关系和构建说明
global.json 定义.NET Core SDK版本
launchSettings.json 应用启动配置
appsettings.json 应用的环境配置
secrets.json 用户秘密
Program.cs 应用启动文件
Startup.cs 应用服务和中间件配置

ASP.NET Core配置源的默认顺序

配置文件内部视角

image

配置文件外部视角

提示:优先级从低到高。

image

Program.cs文件

Program.cs文件中定义了Program类型,是应用程序的入口(entry point for app)。通常在该文件中配置应用的“托管”环境(configure the “hosting” environment)。

Porgram类型定义如下:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

在Main方法中,调用了CreateDefaultBuilder(args)方法

CreateDefaultBuilder用于设置项目的默认配置

调用Host.CreateDefaultBuilder(args)方法中创建了应用的默认的配置构建器

然后调用配置构建器的ConfigureWebHostDefaults方法创建默认的配置

最后调用UseStartup<Startup>()方法来实例化Startup类

Program.cs在ASP.NET Core程序中的位置

image

CreateDefaultBuilder方法使用默认的构建器模式创建一个Web主机

该主机可以指定诸如要使用的Web服务器和配置源之类的东西

以及选择用于完成应用程序服务配置的类

默认情况下使用的Startup类作为服务配置类

Startup.cs文件

Startup.cs文件中定义了Startup类

在Startup类中可以配置应用程序所需的嵌入式或自定义服务

Startup类默认的定义如下:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime.
    // Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
    }

    // This method gets called by the runtime. 
    // Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        app.UseHttpsRedirection();
        app.UseRouting();
        app.UseAuthorization();
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }
}

Startup类构成:一个构造函数+2个方法+1个属性

属性

用于保存配置项的引用

构造函数

用于注入默认的配置项到配置项属性中

ConfigureServices方法

正如方法名描述的用于配置服务

ConfigureServices方法注意:

由于大型应用程序可能包含许多不同的服务

因此ConfigureServices方法中可能会出现很多混乱且无法读取的代码

为了使下一个人和我们自己更具可读性

我们可以将代码结构化为逻辑块,

然后将这些块分成扩展方法

然后在ConfigureServices方法中引用扩展方法

Configure方法

用于向应用程序的请求管道中添加中间件组件

MemoryConfigurationSource(内存配置提供程序)

说明

配置组件内置了内存配置提供程序,可以定义一个键-值对集合作为配置数据源。通常情况下可以使用字典类Dictionary<string, string>来处理。

内存配置提供程序的配置实例:

IConfigurationBuilder builder = new ConfigurationBuilder();
var configData = new Dictionary<string, string>() {
    { "key1 ","v1"},
    { "section1:aaa","v2"}
};
//方法一
builder.Add(new MemoryConfigurationSource { InitialData = configData });

//方法二
builder.AddInMemoryCollection(configData);
IConfigurationRoot root = builder.Build();

上面两种方法是等价的,一种直接构造内存配置数据源,另一种使用了扩展方法。扩展方法被广泛使用,建议在实际项目中使用。

通常情况下,内存配置为程序提供了与环境无关的特定行为的配置,这在定义应用程序时非常有用。明确定义组件使用的配置值,可以避免组件采用隐含的默认配置,使得应用程序的行为更为明确,代码也更易管理。

实例

var builder = WebApplication.CreateBuilder(args);
//定义内存配置项
var mySettings = new Dictionary<string, string> { };
mySettings.Add("Title", "这是标题");
mySettings.Add("Content", "这是内容");

//直接引入加载的内存配置项
builder.Configuration.AddInMemoryCollection(mySettings);

在控制器中使用

//注入配置服务
[HttpGet("ConfigTest")]
public string ConfigTest([FromServices] IConfiguration configuration)
{
    //获得配置文件中的具体值
    return configuration["Title"];
}

Command-Line Arguments(命令行配置提供程序)

说明

命令行配置提供程序可以轻松地将命令行参数作为配置的数据源。要使用命令行配置提供程序,需要安装NuGet包。

默认情况下,ASP.NET Core内置了命令行配置提供程序,无需再安装。

Microsoft.Extensions.Configuration.CommandLine

并使用如下代码将其注册到IConfigurationBuilder中。

static void Main(string[] args)
{
    IConfigurationBuilder builder = new ConfigurationBuilder();
    //将Main函数接收到的命令行参数args传递给提供程序,这样就可以在配置中读取应用程序启动命令传递进来的参数。
    builder.AddCommandLine(args); //添加命令行配置提供程序
    IConfigurationRoot root = builder.Build();
}

使用

基本使用

命令行参数需要遵循如下规则:

  • Key和Value之间可以用等号“=”连接。

  • Key和Value之间使用空格隔开时,Key必须使用“--”或者单斜杠“/”作为前缀。

直接在dotnet CLI命令中加入参数即可

dotnet run PandaKey="PandaValue"
dotnet run CommandLineKey1=value1 CommandLineKey2=value2 CommandLineKey3=value3
dotnet run --CommandLineKey1=value1 --CommandLineKey2=value2 --CommandLineKey3=value3
dotnet run /CommandLineKey1=value1 /CommandLineKey2=value2 /CommandLineKey3=value3

注意:
命令行参数支持不带前置符号。
或使用“--”和“/”作为参数的前置符号。
每个参数由参数名、等号和参数值组成。

参数别名

为了使程序支持简写和全写的命令行参数,可以在自己写个参数列表。然后使用AddCommandLine方法的第二个参数进行自动映射。

static void Main(string[] args)
{
    IConfigurationBuilder builder = new ConfigurationBuilder();
    //自己写个参数列表
    var switchMappings = new Dictionary<string, string>
    {
        { "-k1","key1"},
        { "--k1-full","key1"},
        { "-k2","key2"},
        { "--k2-full","key2"}
    };
    builder.AddCommandLine(args, switchMappings);
    IConfigurationRoot root = builder.Build();
    var key2 = root["key2"];
}

使用方法

dotnet run key2=abc
dotnet run --key2 abc
dotnet run -k2 abc
dotnet run --k3 abc

Environment Variables(环境变量配置提供程序)

环境变量配置说明

在容器化流行的当下,尤其是Kubernetes中,环境变量被广泛使用,这得益于容器的环境隔离能力,使得应用程序运行环境相互独立。使用环境变量作为配置数据源是一个不错的做法。环境变量配置提供程序提供了从环境变量读取配置的能力,因此可以非常轻松地适配容器化环境。

环境变量配置提供程序由包Microsoft.Extensions.Configuration.EnvironmentVariables提供,其核心能力可以概括为:

  • 支持仅加载特定前缀的环境变量,在加载时前缀会从Key中去除。
  • 对于不支持“:”的系统,可以使用双下划线“”表示配置段的分层键。
  • 双下划线“”在加载后会被替换为“:”。

ASP.NET Core中的环境变量

一般情况下ASP.NET Core环境变量分为:

环境类型 环境说明
Development 开发环境
Staging 演示(临时、演示)环境
Production 生产环境

也可以自定义环境变量

比如:Testing 对应测试环境

设置环境变量

编辑launchSettings.json文件设置环境变量

打开launchSettings.json文件,在environmentVariables节点下添加键值对即可。

image

使用Visual Studio GUI编辑环境变量

image

通过系统设置编辑环境变量

直接编辑即可

ASPNETCORE_ENVIRONMENT环境变量原理

ASP.NET Core提供了开箱即用的IWebHostEnvironment服务。使用该服务,可以访问ASPNETCORE_ENVIRONMENT环境变量值。在Configure方法中,默认已经注入该服务了,可以直接使用。可以用于检测当前所在环境、当前环境的名称。

实例:获得当前环境的名称

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.Run(async (content) =>
    {
        //输出环境变量名称值
        await content.Response.WriteAsync(env.EnvironmentName);
    });
}

实例:检测当前所在环境

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    //检测是否开发环境
    if (env.IsDevelopment())
    {
        app.Run(async (content) => {
            await content.Response.WriteAsync("IsDevelopment");
        });
    }

    //检测是否演示环境
    if(env.IsStaging())
    {
        app.Run(async (content) => {
            await content.Response.WriteAsync("IsStaging");
        });
    }

    //检测是否生产环境
    if (env.IsProduction())
    {
        app.Run(async (content) => {
            await content.Response.WriteAsync("IsProduction");
        });
    }

    //检测是否自定义的环境
    if(env.IsEnvironment("Testing"))
    {
        app.Run(async (content) => {
            await content.Response.WriteAsync("Testing");
        });
    }
}

使用环境变量

在命令行中定义环境变量

set Key1="Value1"
set Section1__Key1=Value11
set MyEnv_Key1="MyEnv Value1"
set MyEnv_Section1__Key1="MyEnv Value11"
dotnet run

在代码中使用

IConfigurationBuilder builder = new ConfigurationBuilder();
builder.AddEnvironmentVariables("MyEnv_");  //加载MyEnv_前缀的配置
IConfigurationRoot root = builder.Build();
Console.WriteLine($"Key1:{ root["Key1"]}");
Console.WriteLine($"Section1:Key1:{ root ["Section1:Key1"]}");
Console.WriteLine($"Key1 in Section1:{ root.GetSection("Section1")["Key1"]}");
Console.WriteLine($"MyEnv_Key1:{ root["MyEnv_Key1"]}");
Console.WriteLine($"MyEnv_Section1:Key1:{ root["MyEnv_Section1:Key1"]}");

launchSettings.json(启动配置)

配置文件说明

launchSettings.json 正如其文件名称是一个启动配置文件,位于项目的Properties目录下。用于配置ASP.NET Core应用程序的启动相关的参数,比如包含用于启动IIS和自托管应用程序(Kestrel)设置的配置。Visual Studio和.NET CLI在启动项目的时候,会读取该文件的配置信息。可以使用Visual Studio的GUI方式配置该文件,也可以直接编辑JSON代码。

注意:

  • launchSettings.json文件仅用于本地开发环境,发布时无需带上该文件。

  • 如果需要在部署生产环境时使用配置信息,应存储在appsettings.json文件夹中。

  • appsettings文件还可以配置不同环境,比如appsettings.Development.json。

除了appsettings.json文件,还可以采用其他方式配置程序,比如:环境变量、User Secrets、命令行、自定义参数。

默认项目模板设置的配置项如下:

{
  "$schema": "http://json.schemastore.org/launchsettings.json",
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:18608",
      "sslPort": 44326
    }
  },
  "profiles": {
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": false,
      "launchUrl": "weatherforecast",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "WebApplication6": {
      "commandName": "Project",
      "launchBrowser": false,
      "launchUrl": "weatherforecast",
      "applicationUrl": "https://localhost:5001;http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

其中的具体配置项说明

launchBrowser      		配置项目启动后是否启动浏览器
applicationUrl        	配置应用启动的地址
launchUrl        		配置项目启动后打开的URL的参数
                     	需要配置launchBrowser为true才生效
sslPort           		配置HTTPS/SSL的端口
environmentVariables    配置项目的环境变量
iisSettings          	配置IIS/IIS Express的配置项
iisExpress          	配置只针对IIS Express的配置项
windowsAuthentication    配置IIS是否启用Windows认证
anonymousAuthentication  配置IIS是否启用匿名认证

从配置信息中,可以看到有2个配置信息:IIS Express和 具体项目名称。当在Visual Studio 2022中按F5时,默认调用的是具体项目名称的配置信息。当在Visual Studio 2019中按F5时,默认调用的是IIS Express的配置信息。当然,也可以自己通过Visual Studio中的调试按钮右侧的小箭头进行调整。

image

当使用.NET CLI命令行启动项目的时候,默认使用具体项目名称的配置文件。

通过Visual Studio GUI方式配置launchSettings.json

打开Visual Studio,点击Properties目录,会自动弹出GUI配置界面。打开项目属性界面,切换到“调试”栏。

image

环境变量中的Development,可以换为:Staging、Production。通过切换环境变量,可以在Startup.cs文件中,通过环境变量配置其他配置。

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        //只在开发环境才生效
        app.UseDeveloperExceptionPage();
    }
}

launchSettings.json与appsettings.json的区别

  • 都是配置文件,但ASP.NET Core应用读取的先后不同。

  • 当我们发出dotnet run命令时将加载launchSettings.json文件。

  • launchSettings.json用于开发环境,appsettings.json用于部署环境。

  • appsettings.json在CreateDefaultBuilder方法中使用。

CreateDefaultBuilder方法许多配置源示意图,读取顺序与优先级正好相反。

image

读取配置项的值

直接注入configuration服务,然后调用即可。

public string Test([FromServices] IConfiguration configuration)
{
    string value = configuration["ASPNETCORE_ENVIRONMENT"];
    Console.WriteLine(value);
    return "";
}

launchSettings.json文件 与 项目配置托管模型 的关联

当使用launchSettings.json文件中的不同配置项 和 项目AspNetCoreHostingModel

设置为不同值,会影响启动的服务器类型

CommandName launchSettings配置 AspNetCoreHostingModel 托管模型 Internal Web Server 内部服务器 Extenal Web Server 外部服务器
具体项目名称 忽略托管模型值 只使用IIS Express 只使用IIS Express
IIS Express InProcess 只使用IIS Express 只使用IIS Express
IIS Express OutOfProcess Kestrel IIS Express
IIS InProcess 只使用IIS 只使用IIS
IIS OutOfProcess Kestrel IIS

appsettings.json(应用配置)

配置文件说明

appsettings.json根据不同的环境进行设置只有在指定环境下才启用的配置。

apsettings.{EnvironmentSuffix}.json会覆盖appsettings.json的配置,即具体的环境的配置信息优先。

image

比如可以自定义:

appsettings.Development.json   	用于开发环境
appsettings.Test.json       	用于测试环境
appsettings.Production.json   	用于部署环境
appsetitng文件根据设置的ASPNETCORE_ENVIRONMENT环境变量来进行启用对应设置

比如在不同的操作系统下设置好环境变量后,会触发不同的环境配置

in Windows

set ASPNETCORE_ENVIRONMENT=Production

in Linux

export ASPNET_CORE_ENVIRONMENT=Production

默认项目模板的appsettings.json内容

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

写入配置信息到appsettings.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "PandaKey": "PandaValue" //自定义的配置项
}

读取appsettings.json等配置文件中的配置信息

在需要读取配置项的地方,注入IConfiguration服务,然后直接读取即可

实例:在控制器中使用

using Microsoft.AspNetCore.Mvc;
//引入命名空间
using Microsoft.Extensions.Configuration;

namespace WebApplication2.Controllers
{
    public class PandaController : Controller
    {
        public IConfiguration Configuration { get; set; }
        //在控制器或者方法中注入配置服务
        public string Index([FromServices] IConfiguration configuration)
        {
            this.Configuration = configuration;
            //读取配置项
            return Configuration["PandaKey"];
        }
    }
}

读取多层级的配置项,可以使用冒号:分隔。比如:

//appsetting.json
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  //加入自定义配置项
  "Config1": {
    "SubConfig1": "666"
  }
}

public string Test([FromServices] IConfiguration configuration)
{
    //直接访问配置项的值
    string configValue = configuration["Config1:SubConfig1"];
    Console.WriteLine(configValue ?? "NoValue");
    return "";
}

当配置参数很多的时候一个一个去取参数就很麻烦,这时候配置参数绑定到具体的配置对象的需求就产生了,只需要使用Get方法即可。

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
   //自定义的配置项
  "SubConfig1": "666",
  "SubConfig2": "888",
  "SubConfig3": "999"
}

//自定义配置对象
namespace PandaTest.Configuration
{
    public class PandaConfig
    {
        public string SubConfig1 { get; set; }
        public string SubConfig2 { get; set; }
        public string SubConfig3 { get; set; }
    }
}

//在控制器中使用
public string Test([FromServices] IConfiguration configuration)
{
    //绑定到自定义的配置对象
    PandaConfig pandaConfig = configuration.Get<PandaConfig>();
    Console.WriteLine(pandaConfig.SubConfig1);
    Console.WriteLine(pandaConfig.SubConfig2);
    Console.WriteLine(pandaConfig.SubConfig3);
    return "";
}

User Secrets(用户机密)

secrets.json配置文件说明

​ 在开发过程中,有些信息是机密信息,比如加密密钥,比如:第三方密钥,微信、支付宝、微博密钥。多人进行协同开发中,每个人本地数据库设置的账号和密码也不同。所以将这部分比较机密的配置信息单独放在文件中保存,这就是secrets.json文件。

配置文件secrets.json在ASP.NET Core应用中的位置。

image

Visual Studio GUI方式配置secrets.json

选中【项目】,鼠标右键点击【管理用户机密】。

image

Visual Studio会自动创建一个secrets.json文件,我们可以在里面添加键值对,然后保存文件。

image

Visual Studio会自动在项目配置文件添加节点。

image

该节点中的GUID和secrets.js文件中的GUID是对应的。

secrets.js文件默认存放在

Windows:  %APPDATA%\Microsoft\UserSecrets\<user_secrets_id>\secrets.json
Linux/OSX: ~/.microsoft/usersecrets/<user_secrets_id>/secrets.json

注意:内容都是明文的。

还可以直接使用Visual Studio打开secrets.js文件所在的目录位置。

image

使用dotnet命令行配置secrets.json

使用dotnet user-secrets可以执行用户机密文件的操作。

首先,在项目根目录下执行初始化user secret

dotnet user-secrets init

注意:如果没有该命令,可以安装该工具包。

dotnet tool install --global user-secrets

本质是在项目配置文件.csproj文件中加入UseSecretsId节点。并生成对应的机密文件。

<PropertyGroup>
  <UserSecretsId>8C93C1B2-ABC4-41CB-A81E-EB2A3D675330</UserSecretsId>
</PropertyGroup>

注意:这里的GUID叫做user_secrets_id。

然后 在项目的根目录下执行命令来增加机密配置项:

dotnet user-secrets set “Key” “Value”

比如:将UserID的键值对存储在secrets.json中

dotnet user-secrets set “UserID” “sa”

比如:将Password的键值对存储在secrets.json中

dotnet user-secrets set “Password” “Password”

如果需要存储层级数据可以使用冒号:分隔即可。

dotnet user-secrets set “Key:SubKey” “Value”

具体文件保存在

Windows:  %APPDATA%\Microsoft\UserSecrets\<user_secrets_id>\secrets.json
Linux/OSX: ~/.microsoft/usersecrets/<user_secrets_id>/secrets.json

Windows中的secrets.json文件具体位置:

image

更多的命令操作可以使用--help命令参数查看。

dotnet user-secrets --help
支持的操作:
  clear   Deletes all the application secrets
  init    Set a user secrets ID to enable secret storage
  list    Lists all the application secrets
  remove  Removes the specified user secret
  set     Sets the user secret to the specified value

读取保存的内容

在使用的时候需要使用Configuration对象去使用即可。

using Microsoft.AspNetCore.Mvc;
//引入命名空间
using Microsoft.Extensions.Configuration;

namespace WebApplication2.Controllers
{
    public class PandaController : Controller
    {
        public IConfiguration Configuration { get; set; }
        //在控制器或者方法中注入配置服务
        public string Index([FromServices] IConfiguration configuration)
        {
            this.Configuration = configuration;
            //读取配置项
            return Configuration["PandaKey"];
        }
    }
}

实例:获得数据库配置信息。

var builder = new SqlServerConnectionStringBuilder();
            builder.ConnectionString =
              Configuration.GetConnectionString("SqlConnection");
            builder.Username = Configuration["UserID"];
            builder.Password = Configuration["Password"];
            services.AddDbContext<CommandContext>
                (opt => opt.UseSqlServer(builder.ConnectionString));

File Configuration Provider(文件配置提供程序)

配置说明

SP.NET Core内置了3种格式的配置文件,分别是json、xml、ini,可以通过AddJsonFile、AddXmlFile、AddIniFile来注入对应格式的文件,这些注入方法有4个主要的参数:

  • path:表示配置文件的路径,默认情况下相对于应用程序的运行目录。

  • optional:表示文件是否为可选项。如果指定为true,则忽略文件不存在的情形;如果指定为false,则检测到文件不存在时抛出异常。默认为false。

  • reloadOnChange:表示在文件发生变化时是否重新加载,true表示重新加载变更后的文件,false表示不重新加载,默认为false。

  • provider:表示读取文件的文件提供程序,不传入则表示使用默认的文件提供程序。

此外,框架还提供了AddJsonStream、AddXmlStream、AddIniStream三种方法,可以直接注入文件流。

ConfigurtionBuilder类

ConfigurtionBuilder类位于Microsoft.Extensions.Configuration命名空间。

使用时需要引入命名空间

using Microsoft.Extensions.Configuration;

ConfigurtionBuilder类实现了IConfigurationBuilder接口,该接口包括两个重要的方法。

namespace Microsoft.Extensions.Configuration
{
    public interface IConfigurationBuilder
    {
        IDictionary<string, object> Properties { get; }
        IList<IConfigurationSource> Sources { get; }
        //添加不同形式的配置源
        IConfigurationBuilder.Add(IConfigurationSource source);
        //把所有添加的配置源中配置信息构建(或生成)程序可访问的配置项
        IConfigurationRoot.Build();
    }
}

使用自定义JSON配置文件

测试使用的JSON文件 UISetting.json

{
    "FontFamily": "Arial",
    "FontSize": 16,
    "Editor": {
        "Background": "#F4F4F4",
        "Foreground": "Black"
    }
}

配置Configuration服务

打开Program.cs文件,配置Configuration对象。

注意:如果是在非ASP.NET Core应用中使用配置服务,并且使用JSON作为配置文件,需要安装Microsoft.Extensions.ConfigurationMicrosoft.Extensions.Configuration.Json包。

ASP.NET Core配置中启用JSON配置文件。

var builder = WebApplication.CreateBuilder(args);
//直接引入加载的配置文件即可
builder.Configuration.SetBasePath(Directory.GetCurrentDirectory())			//设置配置文件所在的路径
                   .AddJsonFile("UISetting.json",optional:false, reloadOnChange:true);  //添加JSON文件
//或者从文件流读配置
//builder.AddJsonStream(stream: jsonStream);

//Add services to the container
builder.Services.AddControllers();

Controller中使用

[HttpGet("ConfigTest")]
public string ConfigTest([FromServices] IConfiguration configuration)  //注入配置服务
{
    //获得配置文件中的具体值
    return configuration["Editor:Background"];
}

读取数据的其他方式

//遍历输出配置项
foreach (var item in config.AsEnumerable())
{
    Console.WriteLine($"Key: {item.Key}, Value:{item.Value}");
}

//通过指定索引Key来访问其配置项值
Console.WriteLine("FontFamily: " + config["FontFamily"]);

//通过GetValue方法来访问
Console.WriteLine("FotFamily:" + config.GetValue<int>("FontSize"));
Console.WriteLine("FontSize: " + config.GetValue<int>("FontSize"));

//通过指定索引Key来访问其配置项值(多层级结构)
//使用冒号:即可
Console.WriteLine("Editor Foreground: " + config["Editor:Foreground"]);

//对于层级结构,还可以使用IConfiguration接口的GetSection来访问
var editorSection = config.GetSection("Editor");
Console.WriteLine("Editor Background:" + editorSection["Background"]);

使用自定义XML配置文件

测试使用的XML文件 setting.xml

<?xml version="1.0" encoding="utf-8" ?>
<config>
    <AppInfo>
      <Name>PandaTestApplication</Name>
      <Version>1.0.0</Version>
    </AppInfo>
    <AuthorInfo>
        <Name Code ="666">Panda666</Name>
        <Age>18</Age>
    </AuthorInfo>
</config>

配置Configuration服务

var builder = WebApplication.CreateBuilder(args);
//直接引入加载的配置文件即可
builder.Configuration.SetBasePath(Directory.GetCurrentDirectory())   //设置配置文件所在的路径
                    .AddXmlFile("setting.xml", optional:false, reloadOnChange:true);  //添加xml文件

//或者从文件流读配置
//builder.AddXmlStream(stream: xmlStream);

// Add services to the container.
builder.Services.AddControllers();

在Controller中使用

//注入配置服务
[HttpGet("ConfigTest")]
public string ConfigTest([FromServices] IConfiguration configuration)
{
    //获得配置文件中的具体值
    return configuration["AppInfo:Name"];
}

读取数据的其他方式

//遍历输出配置条目
foreach (var item in config.AsEnumerable())
{
    //输出条目
    Console.WriteLine($"Key: {item.Key}, Value:{item.Value}");
}

//使用字符串索引形式访问
Console.WriteLine("AppInfo:Name: " + config["AppInfo:Name"]);
Console.WriteLine("AppInfo:Version: " + config["AppInfo:Version"]);
Console.WriteLine("AuthorInfo:Name: " + config["AuthorInfo:Name"]);
//访问节点的属性
Console.WriteLine("AuthorInfo:Name:Code: " + config["AuthorInfo:Name:Code"]);
Console.WriteLine("AuthorInfo:Age: " + config["AuthorInfo:Age"]);

//使用GetValue方法访问配置项
Console.WriteLine($"AppInfo:Name = {config.GetValue<string>("AppInfo:Name")}");
Console.WriteLine($"AuthorInfo:Name = {config.GetValue<string>("AuthorInfo:Name")}");

//使用节
var appInfoSection = config.GetSection("AppInfo");
Console.WriteLine($"appInfoSection:AppInfo:Name = {appInfoSection.GetValue<string>("Name")}");
var authorInfoSection = config.GetSection("AuthorInfo");
foreach (var item in appInfoSection.AsEnumerable())
{
    Console.WriteLine($"{item.Key} = {item.Value}");
}
foreach (var item in authorInfoSection.AsEnumerable())
{
    Console.WriteLine($"{item.Key} = {item.Value}");
}

使用自定义INI配置文件

测试使用的ini文件 config.ini

[Info]
Name=ConfigTestApp
Version=1.0
Description="这里是INI文件中的描述"

配置Configuration服务

var builder = WebApplication.CreateBuilder(args);
//直接引入加载的配置文件即可
builder.Configuration.SetBasePath(Directory.GetCurrentDirectory())   //设置配置文件所在的路径
                    .AddIniFile("config.ini", optional:false, reloadOnChange:true);  //添加ini文件

//或者从文件流读配置
//builder.AddIniStream(stream: iniStream);

// Add services to the container.
builder.Services.AddControllers();

Controller中使用

//注入配置服务
[HttpGet("ConfigTest")]
public string ConfigTest([FromServices] IConfiguration configuration)
{
    //获得配置文件中的具体值
    return configuration["Info:Name"];
}

读取数据的其他方式

//遍历输出配置条目
foreach (var item in config.AsEnumerable())
{
    //输出条目
    Console.WriteLine($"Key: {item.Key}, Value:{item.Value}");
}

//使用字符串索引形式访问
Console.WriteLine("AppInfo:Name: " + config["AppInfo:Name"]);
Console.WriteLine("AppInfo:Version: " + config["AppInfo:Version"]);
Console.WriteLine("AuthorInfo:Name: " + config["AuthorInfo:Name"]);

//使用GetValue方法访问配置项
Console.WriteLine($"AppInfo:Name = {config.GetValue<string>("AppInfo:Name")}");
Console.WriteLine($"AuthorInfo:Name = {config.GetValue<string>("AuthorInfo:Name")}");

//使用节
var appInfoSection = config.GetSection("AppInfo");
Console.WriteLine($"appInfoSection:AppInfo:Name = {appInfoSection.GetValue<string>("Name")}");
var authorInfoSection = config.GetSection("AuthorInfo");
foreach (var item in appInfoSection.AsEnumerable())
{
    Console.WriteLine($"{item.Key} = {item.Value}");
}
foreach (var item in authorInfoSection.AsEnumerable())
{
    Console.WriteLine($"{item.Key} = {item.Value}");
}

Reload Configuration(重新加载配置)

方法一:调用IConfiguration或IConfigurationRoot的Reload方法

config.Reload()

方法二:在添加配置源时指定 reloadOnChange 属性

var builder = new ConfigurationBuilder()
				.SetBasePath(Directory.GetCurrentDirectory())
				.AddJsonFile("UISetting.json", optional: true,reloadOnChange: true);

Load Configuration From File(从文件夹加载配置文件)

从文件夹加载配置文件可以使用Key-per-file配置提供程序。Key-per-file配置提供程序可将文件内容整体加载为配置值,可以实现的功能如下:

将指定目录下的文件加载到配置程序中,以文件名作为配置的Key值,以文件内容作为配置的Value值。

通过AddKeyPerFile方法可以加载指定目录的文件,它有两个参数:

  • directoryPath:表示要加载的目录,必须是绝对路径。
  • optional:表示目录是否可选。true表示可选,目录不存在时则忽略;false表示必选,目录不存在时则抛出异常。

实例:

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration(builder =>
        {
            //加载配置文件所在的文件夹
            var configFileDir = Path.Combine(Directory.GetCurrentDirectory(), "Configs");
            //加载文件夹下的配置文件
            builder.AddKeyPerFile(directoryPath: configFileDir, optional: false);
        })
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });

Strong Type(配置强类型对象)

作用

把配置项映射到具体的类型中

访问对象及其属性要比直接访问配置方便

实现

测试使用的配置项 PandaConfig.json

{
  "FontSize": 16,
  "FontColor": "Red"
}

创建一个包含同样信息的类来表示其中的配置信息

PandaConfig.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace WebApplication1
{
    public class PandaConfig
    {
        public int FontSize { get; set; }
        public string FontColor { get; set; }
    }
}

在Startup.cs文件中定义配置强类型

public Startup(IConfiguration configuration)
{
    Configuration = new ConfigurationBuilder()
                    .SetBasePath(Directory.GetCurrentDirectory())
                    .AddJsonFile("PandaConfig.json")
                    .Build();
}

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<PandaConfig>(Configuration);
}

Custom Configuration Source(自定义配置源)

说明

使用自定义配置源可以读取特定格式配置文件中的内容

也可以灵活地从配置文件中读取所需要的内容

操作方法

要创建自定义配置源,需要用到两个接口

IConfigurationSource接口

public interface IConfigurationSource
{
    IConfigurationProvider Build(IConfigurationBuilder builder);
}

IconfigurationProvider接口

public interface IConfigurationBuilder
{
    IDictionary<string, object> Properties { get; }
    IList<IConfigurationSource> Sources { get; }
    IConfigurationBuilder Add(IConfigurationSource source);
    IConfigurationRoot Build();
}

实例:实现加载web.config文件

当要创建的配置源也是基于文件时

可以使用 FileConfigurationSource 和 FileConfigurationProvider 类

两个类分别实现了上述的两个接口,这样就不需要直接去实现上述接口

创建AppSettingsConfigurationSource类

并使它继承FileConfigurationSource类

public class AppSettingsConfigurationSource : FileConfigurationSource
{
    public AppSettingsConfigurationSource(string path)
    {
        Path = path;
        ReloadOnChange = true;
        Optional = true;
        FileProvider = null;
    }
    public override IConfigurationProvider Build(IConfigurationBuilder builder)
    {
        FileProvider = FileProvider ?? builder.GetFileProvider();
        return new AppSettingsConfigurationProvider(this);
    }
}

创建AppSettingsConfigurationProvider类
继承自FileConfigurationProvider类

public class AppSettingsConfigurationProvider : FileConfigurationProvider
{

    public AppSettingsConfigurationProvider(AppSettingsConfigura tionSource source) : base(source)
    { 

    }

    public override void Load(Stream stream)
    {
        try
        {
            Data = ReadAppSettings(stream);
        }
        catch
        {
            throw new Exception("读取配置信息失败,可能是文件内容不正确");
        }
    }

    private IDictionary<string, string> ReadAppSettings(Stream stream)
    {
        var data = new SortedDictionary<string, string>(StringComparer.OrdinalIgnoreCase);
        var doc = new XmlDocument();
        doc.Load(stream);
        var appSettings = doc.SelectNodes("/configuration/appSettings/add");
        foreach (XmlNode child in appSettings)
        {
            data[child.Attributes["key"].Value] = child.Attributes["value"].Value;
        }
        return data;
    }

为了方便使用自定义配置源

可以为IConfigurationBuilder类创建一个扩展方法

public static class AppSettingConfigurationExtensions
{
    public static IConfigurationBuilder AddAppSettings(this IconfigurationBuilder builder, string path)
    {
        return builder.Add(new AppSettingsConfigurationSource(path));
    }
}

开始使用

var builder = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddAppSettings("web.config");

配置项细节问题

配置项大小写问题

配置项键名不区分大小写

配置项重复问题

同一种类型的配置源可以添加多个,如添加多个JSON格式的配置文件

当指定了多个配置源时,系统会按照顺序加载每个源中的配置项

如果配置源中存在相同键名的配置项,则后面的会将前面的值覆盖

建议将命令行参数配置源作为最后添加的配置源

这样会使命令行参数中的配置项具有最高优先级

它会覆盖之前可能出现过的同名配置项

环境变量配置项冒号问题

当通过环境变量向应用添加配置项时

如果操作系统平台不支持用冒号表示配置项的层次关系

则可以使用双下划线代替冒号,如Editor__Background

不默认支持的配置文件格式

ASP.NET Core提供的配置源中并不支持对web.config或app.config

需要支持这两种或其他类型的配置文件,需要自定义实现配置源

Option(选项组件)

说明

组件定义自己专属的配置对象,也可以叫作选项类,这种设计模式称为选项模式。

使用选项模式可以得到如下好处:

  • 符合接口分离原则(ISP)、封装原则,服务、组件仅依赖其用到的配置,而不是整个配置,如IConfiguration对象,它代表了整个应用加载的所有配置,在类中依赖它意味着依赖了整个配置,不符合封装原则。

  • 符合关注点分离原则,为服务、组件分别定义选项类,它们之间不相互依赖,确保了组件的独立性。

选项组件主要包含在下列组件包(ASP.NET Core框架已经默认包含了它们)中:

Microsoft.Extensions.Options
Microsoft.Extensions.Options.ConfigurationExtensions
Microsoft.Extensions.Options.DataAnnotations

选项的注入与使用

选项框架提供了一组Configure<TOptions>扩展方法来注入选项类,可以将配置段Section传入并与其绑定,其中选项类满足下面的条件:

  • 必须是非抽象类。
  • 必须包含无参数的Public的构造函数。
  • 默认绑定所有Public设置了Get、Set属性,可以通过设置支持Private的Set属性。
  • 不会绑定字段。

使用实例

先定义一个存储Option的自定义类型

public class MyOption
{
    public string Name { get; set; }
    public int MinAge { get; set; }
    public string Title { get; set; }
}

通过扩展方法Configure注入MyOption服务:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }
    public void ConfigureServices(IServiceCollection services)
    {
        //注入MyOption选项类
        services.Configure<MyOption>(Configuration.GetSection("myOption"));
        //或者使用下面的代码
        
        //注入并设置允许绑定私有属性
        services.Configure<MyOption>(Configuration.GetSection("myOption"), binder =>
                                     {
                                         binder.BindNonPublicProperties = true;
                                     });
       
        services.AddControllersWithViews();
    }
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        //…
    }
}

在Service和Controller中使用Option:

public class MyService
{
    IOptions<MyOption> _options;
    public MyService(IOptions<MyOption> options)
    {
        _options = options;
    }
    //其他代码
}

支持注入的IOptions类型

实际上选项框架提供了多个Options接口供选择:

IOptions<out TOptions>:

它的生命周期为单例模式,可以注入任意生命周期的服务中。

不支持配置变更跟踪。不支持命名选项。

适用场景:仅初始化时一次读取,不关心配置变化的服务。

IOptionsSnapshot<TOptions>

它的生命周期为Scope模式,可以注入生命周期为Scope的服务中。

每个Scope都会重新计算选项值,因此可以读到最新的配置值。

支持命名选项。

适用场景:生命周期为Scope且期望在配置变更后使用新值的服务。

IOptionsMonitor<TOptions>

它的生命周期为单例,可以注入任意生命周期的服务中。

它提供了配置变更通知的能力。

支持命名选项。

适用场景:生命周期为单例,并且关心配置变更的服务。

实例:使用IOptionsMonitor类型进行注入

public class MyService2
{
    IOptionsMonitor<MyOption> _options;
    public MyService2(IOptionsMonitor<MyOption> options)
    {
        _options = options;
        _options.OnChange(option =>
                          {
                              Console.WriteLine("配置变化了");
                          });
    }
}

相同命名问题处理

当我们需要在应用中对同一选项类的不同实例配置不同的值时,可以使用命名选项。在使用Configure<TOptions>时传入name参数,为不同的配置实例指定名称,同时注入各自的配置段,例如使用下面的配置文件:

//默认配置使用Section myOption
services.Configure<MyOption>(Configuration.GetSection("myOption"));
//名称为myOption2的配置使用Section myOption2
services.Configure<MyOption>("myOption2", Configuration.GetSection("myOption2"));

通过OptionsMonitor<TOptions>的Get方法来读取命名选项类实例:

public class MyService2
{
    IOptionsMonitor<MyOption> _options;
    public MyService2(IOptionsMonitor<MyOption> options)
    {
        _options = options;

        //默认配置
        var option = _options.CurrentValue;

        //读取命名配置
        var namedOption = _options.Get("myOption2");

        _options.OnChange(option =>
                          {
                              Console.WriteLine("配置变化了");
                          });
    }
}

验证选项

在需要对选项类值的有效性进行验证的情况下,可以借助选项框架的验证功能来实现选项值的验证。

注入验证逻辑有3种方式:

  • 通过DataAnnotations。
  • 通过验证委托。
  • 通过实现IValidateOptions接口。
public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }
    
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddOptions<MyOption>()
            .Bind(Configuration.GetSection("myOption"))
            .ValidateDataAnnotations()  //启用DataAnnotations验证
            .Validate(option =>        //启用委托验证
                      {
                          return option.MinAge >= 0;
                      }, "MinAge不能小于0");

        //启用IValidateOptions验证
        services.AddSingleton<IValidateOptions<MyOption>, MyOptionValidation>();  


        //其他代码
    }
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        //…
    }
}

注意:要使DataAnnotations方式生效,则需要为选项类添加验证注解。

使用IValidateOptions<MyOption>验证方式,MyOptionValidation.cs的实现参考:

public class MyOptionValidation : IValidateOptions<MyOption>
{
    public ValidateOptionsResult Validate(string name, MyOption options)
    {
        if (options.MinAge < 0)
        {
            return ValidateOptionsResult.Fail("MinAge不能小于0");
        }
        return ValidateOptionsResult.Success;
    }
}

标签:Core,ASP,配置文件,builder,配置,json,Configuration,public
From: https://www.cnblogs.com/cqpanda/p/16834832.html

相关文章

  • iOS数据持久化 - CoreData
    前言1-CoreData是苹果公司封装的进行数据持久化的框架,首次在iOS3.0版本系统中出现,它允许按照实体-属性-值模型组织数据,并以XML、二进制文件或者SQLite数据文件的......
  • .net core独立部署到Linux问题点总结
    1.修改配置文件:将所有路径改成Linux下的路径;如果使用了log4net,记得修改日志保存路径;2.发布时选择独立部署、目标运行时选择Linux;3.如是是用mysql,记得在etc/my.cnf的配置......
  • 学习ASP.NET Core Blazor编程系列九——服务器端校验
    学习ASP.NETCoreBlazor编程系列一——综述学习ASP.NETCoreBlazor编程系列二——第一个Blazor应用程序(上)学习ASP.NETCoreBlazor编程系列二——第一个Blazor应......
  • VS2017 IIS 部署.net core web项目
    直接上内容: 安装IIS这个不在重复,可百度搜索到。 点击IIS查看模块:查看是否安装了AspNetCoreModule模块,如果没有安装可下载:​​http://download.microsoft.com/downlo......
  • sparkCore
    spark第二天1、打包代码到yarn上运行将代码提交到Yarn.上运行1、将setMaster代码注释,使用提交命令设置运行方式2、修改输入输出路径,并准备数据3、打包上传至服务器4......
  • ASP.NET Core教程-基础介绍(Basic)
    更新记录转载请注明出处:2022年10月30日发布。2022年10月28日从笔记迁移到博客。ASP.NETCore基础ASP.NETCore介绍WebFrameworkcreatedbyMicrosoftforbuil......
  • 基于CV18xx开启coredump
    一:切到SDK目录,sourceanddefconfig对应的board配置eg. sourcebuild/cvisetup.shdefconfigcv1800b_wdmb_0008a_spinor二:透过命令 menuconfi......
  • 快读《ASP.NET Core技术内幕与项目实战》WebApi3.1:WebApi最佳实践
    本节内容,涉及到6.1-6.6(P155-182),以WebApi说明为主。主要NuGet包:无 一、创建WebApi的最佳实践,综合了RPC和Restful两种风格的特点1//定义Person类和ErrorInfo类2pub......
  • Logstash同时运行多个配置文件
    创建存放logstash配置文件存放目录mkdirlogstash-7.17.0/conf.d修改pipelines.yml进行配置vimlogstash-7.17.0/config/pipelines.yml-pipeline.id:all.logqu......
  • Building a ASP.NET solution from command-line?从命令行构建 ASP.NET 解决方案?
    【问题标题】:BuildingaASP.NETsolutionfromcommand-line?从命令行构建ASP.NET解决方案?【发布时间】:2011-01-1406:43:06【问题描述】:如何从命令行构建ASP.NETWe......