写C#程序时,数据库连接字符串、第三方接口地址、超时时间这些经常变动的参数,如果直接写死在代码里,每次改环境都要重新编译发布一遍,非常折腾。正确的做法是把它们抽到配置文件中,程序运行时动态读取。在.NET Core以及后续的.NET版本里,官方钦定的配置文件就是appsettings.json,本文就完整讲一遍它的读取方法。

一、appsettings.json的结构和基本读取原理
先来看一个典型的appsettings.json文件长什么样。它本质上就是一个JSON文档,支持嵌套层级,用冒号分隔的路径就能定位到任意一个节点:
{
"ConnectionStrings": {
"Default": "Server=localhost;Database=test;User Id=sa;Password=123456;"
},
"Logging": {
"LogLevel": {
"Default": "Information"
}
},
"AppSettings": {
"ApiUrl": "https://api.ipipp.com/v1",
"Timeout": 30,
"EnableCache": true
}
}读取配置的核心接口是IConfiguration。在ASP.NET Core的Web项目中,框架在启动时已经自动加载了appsettings.json,并通过依赖注入把它注册进了容器,所以在控制器里直接声明一个IConfiguration类型的构造函数参数就能用:
public class HomeController : Controller
{
private readonly IConfiguration _config;
public HomeController(IConfiguration config)
{
_config = config;
}
public IActionResult Index()
{
// 用索引器读取,节点不存在时返回null
string apiUrl = _config["AppSettings:ApiUrl"];
string connStr = _config.GetConnectionString("Default");
return Content(apiUrl);
}
}注意索引器的路径写法:层级之间用英文冒号连接,比如AppSettings:ApiUrl对应JSON里AppSettings节点下的ApiUrl属性。索引器返回的永远是字符串,如果配置里是数字或布尔值,读出来也是字符串形式。另外GetConnectionString是专门读ConnectionStrings节点的快捷方法,等价于_config["ConnectionStrings:Default"]。
二、控制台程序怎么加载appsettings.json
Web项目里配置是自动加载的,但控制台应用、类库项目、WinForm程序默认不会读这个文件,需要手动构建配置。首先通过NuGet安装三个包:Microsoft.Extensions.Configuration.Json负责JSON文件支持,Microsoft.Extensions.Configuration.Binder负责后面的强类型绑定。安装后在Program.cs里这样写:
using Microsoft.Extensions.Configuration;
var builder = new ConfigurationBuilder()
.SetBasePath(AppContext.BaseDirectory) // 设置配置文件所在目录
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
IConfiguration config = builder.Build();
Console.WriteLine(config["AppSettings:ApiUrl"] ?? "未配置");这里有几个参数值得留意。SetBasePath指定基础目录,用AppContext.BaseDirectory可以保证编译输出目录下也能找到文件;如果写死成项目目录,发布到别的机器就会报找不到文件的错。optional设为false表示文件必须存在,否则启动就抛异常;reloadOnChange设为true后,文件内容变化会自动热更新,改完配置不用重启程序,下一次读取就能拿到新值。
还有个新手常踩的坑:appsettings.json默认不会被复制到输出目录。需要在解决方案资源管理器里右键该文件,选属性,把“复制到输出目录”改成“如果较新则复制”或“始终复制”,否则运行时找不到文件,程序直接崩。
三、读取配置的几种常用写法对比
1. GetValue方法读取并转换类型
索引器只能拿字符串,碰到数字、布尔值还得自己int.Parse,一旦配置写错就抛异常。GetValue提供了泛型版本,读不出还能给默认值,稳妥得多:
int timeout = _config.GetValue<int>("AppSettings:Timeout", 60);
bool enableCache = _config.GetValue<bool>("AppSettings:EnableCache", false);2. GetSection取出整段配置
GetSection返回一个IConfigurationSection对象,代表某个节点本身,可以继续往下钻,也可以判断节点是否存在:
var section = _config.GetSection("AppSettings");
if (section.Exists())
{
string apiUrl = section["ApiUrl"];
}3. 强类型绑定,推荐的方式
配置项多了以后,到处写_config["AppSettings:xxx"]既难维护又容易拼错key。更优雅的做法是定义一个和JSON结构对应的实体类,一次性绑定:
public class AppSettingOptions
{
public string ApiUrl { get; set; }
public int Timeout { get; set; }
public bool EnableCache { get; set; }
}
// 方式一:Bind
var options = new AppSettingOptions();
_config.GetSection("AppSettings").Bind(options);
// 方式二:Get,写法更简洁
var opts = _config.GetSection("AppSettings").Get<AppSettingOptions>();绑定时属性名和JSON里的key不区分大小写,自动匹配。JSON里有而实体类没有的字段会被忽略,实体类有而JSON缺失的字段保持类型默认值,不会报错。在ASP.NET Core里还可以配合services.Configure<T>走选项模式,通过注入IOptions<T>拿到配置,这里就不展开了。
四、多环境配置:appsettings.Development.json是怎么回事
细心的你会发现项目里除了appsettings.json,往往还有appsettings.Development.json。这是.NET的多环境覆盖机制:程序启动时先加载基础配置文件,再根据当前环境变量ASPNETCORE_ENVIRONMENT的值加载对应的appsettings.{Environment}.json,后加载的会覆盖前面的同名配置。
举个例子,开发环境连本地库、生产环境连线上库,两个文件分别这样写:
// appsettings.Development.json
{
"ConnectionStrings": {
"Default": "Server=localhost;Database=test_dev;"
}
}
// appsettings.Production.json
{
"ConnectionStrings": {
"Default": "Server=10.0.0.5;Database=test_prod;"
}
}代码里只需要写_config.GetConnectionString("Default")这一行,不用写任何if判断,框架会根据环境自动选对连接字符串。公共配置放appsettings.json,环境差异配置放各自的文件,这个分层思路能省掉大量运维上的麻烦。需要注意环境变量只决定加载哪个文件,发布前记得确认服务器的环境变量设置是否正确,否则线上可能会读到开发库的配置,这种事故并不少见。
总结
读取appsettings.json的核心就三条路:简单场景用索引器_config["节点:子节点"];需要类型转换用GetValue<T>;配置项多就定义实体类配合Get<T>做强类型绑定。控制台程序记得手动ConfigurationBuilder构建并设置文件复制到输出目录。把这些掌握了,再去看选项模式和分布式配置中心(比如Apollo、Consul)就会顺畅很多,因为它们底层用的也是同一套IConfiguration抽象。
C#配置文件appsettings.jsonIConfiguration修改时间:2026-09-10 02:52:33