Configuration (Cấu hình) trong ASP.NET Core
Cấu hình ứng dụng trong ASP.NET Core được thực hiện bằng cách sử dụng một hoặc nhiều configuration providers (nhà cung cấp cấu hình). Configuration providers đọc dữ liệu cấu hình từ các cặp key-value sử dụng nhiều nguồn cấu hình khác nhau:
- Các file settings, chẳng hạn như
appsettings.json - Biến môi trường, bao gồm Azure App configuration
- Azure Key Vault
- Command-line arguments
- Custom providers, được cài đặt hoặc tạo ra
- Các đối tượng .NET trong bộ nhớ
Bài viết này cung cấp thông tin về cấu hình trong ASP.NET Core. Để biết thông tin về sử dụng cấu hình trong các ứng dụng không phải ASP.NET Core, xem .NET Configuration.
Cảnh báo bảo mật: Bài viết này thể hiện việc sử dụng connection strings. Khi sử dụng database cục bộ cho development và testing, không cần xác thực user database thông qua connection string. Trong môi trường production, connection strings đôi khi bao gồm mật khẩu để xác thực truy cập database. Thông tin đăng nhập trong connection string là rủi ro bảo mật cần tránh trong production app.
Đọc giá trị cấu hình
Cấu hình thường được đọc bằng cách resolve service IConfiguration (Microsoft.Extensions.Configuration namespace) và sử dụng key của các cặp key-value cấu hình để lấy giá trị cấu hình.
Đoạn code Razor component sau đây cho thấy cách lấy giá trị cấu hình, địa chỉ email liên hệ kỹ thuật, từ cấu hình theo key TechnicalContactEmail:
@inject IConfiguration Config Technical Contact: @Config["TechnicalContactEmail"]
Cấu hình ứng dụng và host
ASP.NET Core app cấu hình và khởi động một host (máy chủ lưu trữ). Host chịu trách nhiệm khởi động ứng dụng và quản lý vòng đời. Các cặp key-value cấu hình host được bao gồm trong cấu hình ứng dụng.
Cấu hình ứng dụng có độ ưu tiên cao nhất. Để biết thêm về cách sử dụng configuration providers khi host được xây dựng, xem ASP.NET Core fundamentals overview.
Nguồn cấu hình ứng dụng mặc định
ASP.NET Core web app gọi WebApplication.CreateBuilder để khởi tạo instance mới của class WebApplicationBuilder với các defaults đã cấu hình sẵn:
var builder = WebApplication.CreateBuilder(args);
Cấu hình ứng dụng mặc định được tải theo thứ tự sau, từ ưu tiên cao nhất đến thấp nhất:
- Command-line arguments sử dụng Command-line Configuration Provider.
- Biến môi trường không có tiền tố
ASPNETCORE_hoặcDOTNET_sử dụng Environment Variables Configuration Provider. - User secrets khi ứng dụng chạy trong môi trường
Development. - File cấu hình ứng dụng theo môi trường thông qua
appsettings.{ENVIRONMENT}.json. - File cấu hình ứng dụng chung thông qua
appsettings.json. - Cấu hình host dự phòng (fallback host configuration).
Nguồn cấu hình host mặc định
Nguồn cấu hình host mặc định từ ưu tiên cao nhất đến thấp nhất khi áp dụng cho cấu hình web app (WebApplicationBuilder):
- Command-line arguments sử dụng Command-line Configuration Provider.
- Biến môi trường có tiền tố
DOTNET_sử dụng Environment Variables Configuration Provider. - Biến môi trường có tiền tố
ASPNETCORE_sử dụng Environment Variables Configuration Provider.
Biến môi trường host
Các biến sau được đặt sớm trong quá trình khởi tạo host builder và không thể bị ảnh hưởng bởi cấu hình ứng dụng:
- Application name (Tên ứng dụng)
- Environment name (Tên môi trường)
- Content root
- Web root
- Có quét các hosting startup assemblies không và assembly nào cần quét.
Các host settings khác được đọc từ cấu hình ứng dụng thay vì host configuration.
URLS là một trong nhiều host settings phổ biến không được bootstrapped bởi host configuration. URLS được đọc sau này từ cấu hình ứng dụng.
Bảo mật và user secrets
Hướng dẫn về dữ liệu cấu hình:
- Không bao giờ lưu trữ mật khẩu hoặc dữ liệu nhạy cảm khác trong code configuration provider hoặc trong các file cấu hình plain text. Tool Secret Manager có thể được sử dụng để lưu trữ secrets trong quá trình development.
- Không sử dụng production secrets trong môi trường development hoặc test.
- Chỉ định secrets bên ngoài dự án để chúng không thể vô tình được commit vào source code repository.
Truy cập cấu hình với Dependency Injection (DI)
Cấu hình có thể được inject vào services sử dụng Dependency Injection (DI) bằng cách resolve service IConfiguration. Trong ví dụ sau, giá trị cấu hình được lưu trữ cho configuration key được đại diện bởi placeholder {KEY} được gán cho value:
public class CustomService(IConfiguration config)
{
public void CustomMethod()
{
var value = config["{KEY}"];
}
}Truy cập cấu hình trong file Program
Đoạn code sau truy cập cấu hình trong file Program sử dụng WebApplicationBuilder.Configuration (builder.Configuration):
var defaultConnectionString =
builder.Configuration.GetValue<string>("ConnectionStrings:DefaultConnection");Sau khi ứng dụng được xây dựng (sau dòng var app = builder.Build();), sử dụng WebApplication.Configuration (app.Configuration):
var defaultLogLevel = app.Configuration.GetValue<string>("Logging:LogLevel:Default");Hiển thị configuration settings khi khởi động để debug
Đoạn code sau hiển thị các cặp key-value cấu hình của ứng dụng khi khởi động. Đặt code sau trong file Program (sau dòng var app = builder.Build();), bao gồm compiler directive cho cấu hình DEBUG:
#if DEBUG
foreach (var c in app.Configuration.AsEnumerable())
{
Console.WriteLine($"CONFIG: Key: {c.Key} Value: {c.Value}");
}
#endifConfiguration keys (Khóa cấu hình) và values (giá trị)
Configuration keys:
- Không phân biệt chữ hoa/thường. Ví dụ,
ConnectionStringvàconnectionstringđược coi là các key tương đương. - Nếu một key và value được đặt bởi nhiều hơn một configuration provider, giá trị từ provider cuối cùng được thêm vào sẽ được sử dụng.
- Hierarchical keys (khóa phân cấp)
- Trong Configuration API, dấu phân cách colon (
:) hoạt động trên tất cả các nền tảng. - Trong biến môi trường, dấu phân cách colon không hoạt động trên tất cả nền tảng. Double underscore (
__) được hỗ trợ bởi tất cả nền tảng và tự động được chuyển đổi thành colon (:) khi cấu hình được đọc bởi ứng dụng.
Configuration values là các chuỗi. Giá trị null không thể được lưu trong cấu hình hoặc được bind với các đối tượng.
Cách tổ chức dữ liệu cấu hình phân cấp
Configuration API đọc dữ liệu cấu hình phân cấp bằng cách làm phẳng dữ liệu phân cấp với việc sử dụng dấu phân cách trong configuration keys, thường là colon (:). Double underscore (__) thường được sử dụng với cấu hình biến môi trường để hỗ trợ đa nền tảng.
Trong các tình huống cấu hình ứng dụng phức tạp, tốt nhất là nhóm và đọc dữ liệu cấu hình phân cấp liên quan bằng cách sử dụng options pattern.
Xem xét dữ liệu cấu hình phân cấp sau:
- ConnectionStrings
- DefaultConnection (Value = 'Data Source=LocalSqlServer\MSSQLDev;')
- Logging
- LogLevel
- Default (Value = 'Information')
- Microsoft (Value = 'Warning')
- Microsoft.Hosting.Lifetime (Value = 'Information')
- AllowedHosts (Value = '\*')
Bảng sau hiển thị các keys được sử dụng để lấy các giá trị:
| Key (colon delimiter) | Key (double-underscore delimiter) |
|---|---|
ConnectionStrings:DefaultConnection | ConnectionStrings__DefaultConnection |
Logging:LogLevel:Default | Logging__LogLevel__Default |
Logging:LogLevel:Microsoft | Logging__LogLevel__Microsoft |
Logging:LogLevel:Microsoft.Hosting.Lifetime | Logging__LogLevel__Microsoft.Hosting.Lifetime |
AllowedHosts | AllowedHosts |
Configuration providers (Nhà cung cấp cấu hình)
Bảng sau hiển thị các configuration providers có sẵn cho ASP.NET Core app.
| Provider | Cung cấp cấu hình từ… |
|---|---|
| Azure Key Vault Configuration Provider | Azure Key Vault |
| Azure App Configuration Provider | Azure App Configuration |
| Command-line Configuration Provider | Command-line parameters |
| Custom configuration provider | Nguồn tùy chỉnh |
| Environment Variables Configuration Provider | Biến môi trường |
| File Configuration Provider | Các file INI, JSON và XML |
| Key-Per-File Configuration Provider | Các file trong thư mục |
| Memory Configuration Provider | Collections trong bộ nhớ |
| User secrets | File trong thư mục user profile |
Configuration sources được đọc theo thứ tự mà các configuration providers của chúng được chỉ định. Sắp xếp các configuration providers trong code để phù hợp với các ưu tiên cho các cấu hình nguồn mà ứng dụng yêu cầu.
Một chuỗi điển hình của các configuration providers là:
- Cài đặt ứng dụng chung qua
appsettings.json. - Cài đặt ứng dụng theo môi trường qua
appsettings.{ENVIRONMENT}.json. - User secrets.
- Biến môi trường sử dụng Environment Variables Configuration Provider.
- Command-line arguments sử dụng Command-line Configuration Provider.
Cấu hình file app settings (appsettings.json, appsettings.{ENVIRONMENT}.json)
Đọc cấu hình được tải từ các file app settings bằng cách sử dụng JSON Configuration Provider.
Xem xét file appsettings.json sau:
{
"ConnectionStrings": {
"DefaultConnection": "Data Source=LocalSqlServer\\MSSQLDev;"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}Ví dụ Razor component AppSettingsConfiguration đọc chuỗi kết nối database mặc định và cấu hình mức logging mặc định:
@page "/app-settings-configuration"
@inject IConfiguration Config
<h1>App Settings Configuration</h1>
<ul>
<li>Default Connection String: @Config["ConnectionStrings:DefaultConnection"]
<li>Default Log Level: @Config["Logging:LogLevel:Default"]
</ul>Theo mặc định, các instance JsonConfigurationProvider tải cấu hình theo thứ tự sau:
appsettings.jsonappsettings.{ENVIRONMENT}.json, theo environment của ứng dụng.
Các file appsettings.{ENVIRONMENT}.json sẽ ghi đè keys trong appsettings.json.
Environment Variables Configuration Provider
Environment Variables Configuration Provider mặc định tải cấu hình từ các biến môi trường không có tiền tố ASPNETCORE_ hoặc DOTNET_.
Dấu phân cách colon (:) không hoạt động với hierarchical keys của biến môi trường trên tất cả nền tảng. Ví dụ, Bash không hỗ trợ colon (:) làm dấu phân cách. Tất cả nền tảng hỗ trợ cú pháp double underscore (__) và tự động thay thế nó thành colon (:).
Tiền tố tùy chỉnh cho biến môi trường
Bạn có thể thêm configuration provider cho các biến môi trường có tiền tố tùy chỉnh. Trong file Program, gọi AddEnvironmentVariables với chuỗi để chỉ định tiền tố:
builder.Configuration.AddEnvironmentVariables(prefix: "CustomPrefix_");
Biến môi trường launch settings ghi đè cài đặt biến môi trường
Biến môi trường được đặt trong launchSettings.json ghi đè những biến được đặt trong system environment.
Tiền tố connection string
Configuration API có các quy tắc xử lý đặc biệt cho biến môi trường connection string. Các biến môi trường với các tiền tố sau được tải vào ứng dụng với cấu hình mặc định:
| Tiền tố connection string | Provider |
|---|---|
CUSTOMCONNSTR_ | Custom provider |
MYSQLCONNSTR_ | MySQL |
SQLAZURECONNSTR_ | Azure SQL Database |
SQLCONNSTR_ | SQL Server |
Command-line
Sử dụng các nguồn cấu hình mặc định, CommandLineConfigurationProvider tải cấu hình từ các cặp key-value command-line argument sau các nguồn cấu hình sau:
- Các file
appsettings.jsonvàappsettings.{ENVIRONMENT}.json. - App secrets trong môi trường
Development. - Biến môi trường.
Command-line arguments
Lệnh dotnet run sau đây đặt keys và values sử dụng dấu bằng (=):
dotnet run ConnectionStrings:DefaultConnection="Data Source=LocalSqlServer\\MSSQLDev;" Logging:LogLevel:Default=Information
Lệnh sau đặt keys và values sử dụng dấu gạch chéo (/):
dotnet run /ConnectionStrings:DefaultConnection "Data Source=LocalSqlServer\\MSSQLDev;" /Logging:LogLevel:Default Information
Lệnh sau đặt keys và values sử dụng double dashes (--):
dotnet run --ConnectionStrings:DefaultConnection "Data Source=LocalSqlServer\\MSSQLDev;" --Logging:LogLevel:Default Information
Switch mappings (Ánh xạ switch)
Switch mappings (ánh xạ switch) cho phép logic thay thế tên key thông qua dictionary của switch replacements được truyền vào phương thức AddCommandLine.
var switchMappings =
new Dictionary<string, string>(){ { "-k1", "key1" }, { "-k2", "key2" } };
builder.Configuration.AddCommandLine(args, switchMappings);Đặt môi trường và command-line arguments với Visual Studio
Môi trường và command-line arguments có thể được đặt trong Visual Studio từ hộp thoại launch profiles:
- Trong Solution Explorer, nhấp chuột phải vào project và chọn Properties.
- Chọn tab Debug > General và chọn Open debug launch profiles UI.
File Configuration Provider
FileConfigurationProvider là class base để tải cấu hình từ file system. Các configuration providers sau kế thừa từ FileConfigurationProvider:
- INI Configuration Provider
- JSON Configuration Provider
- XML Configuration Provider
INI Configuration Provider
IniConfigurationProvider tải cấu hình từ các cặp key-value trong file INI:
[ConnectionStrings] DefaultConnection="Data Source=LocalSqlServer\\MSSQLDev;" [Logging:LogLevel] Default=Debug Microsoft=Debug
builder.Configuration
.AddIniFile("IniConfig.ini", optional: false, reloadOnChange: true);
.AddIniFile($"IniConfig.{builder.Environment.EnvironmentName}.ini", optional: true);JSON Configuration Provider
JsonConfigurationProvider tải cấu hình từ các cặp key-value trong file JSON:
builder.Configuration.AddJsonFile("config.json", optional: true, reloadOnChange: true);XML Configuration Provider
XmlConfigurationProvider tải cấu hình từ các cặp key-value trong file XML:
builder.Configuration
.AddXmlFile("XmlFile.xml", optional: false, reloadOnChange: true);
.AddXmlFile($"XmlFile.{builder.Environment.EnvironmentName}.xml", optional: true);Key-Per-File Configuration Provider
KeyPerFileConfigurationProvider sử dụng các file trong thư mục làm các cặp key-value cấu hình. Key là tên file. Value chứa nội dung file. Key-Per-File Configuration Provider được sử dụng trong các tình huống Docker hosting.
var path = Path.Combine(Directory.GetCurrentDirectory(), "path/to/files"); builder.Configuration.AddKeyPerFile(directoryPath: path, optional: true);
Memory Configuration Provider
MemoryConfigurationProvider sử dụng một in-memory collection (tập hợp trong bộ nhớ) làm các cặp key-value cấu hình:
var configSettings = new Dictionary<string, string>
{
{ "ConnectionStrings:DefaultConnection", "Data Source=LocalSqlServer\\MSSQLDev;" },
{ "Logging:LogLevel:Default", "Information" }
};
builder.Configuration.AddInMemoryCollection(configSettings);Cấu hình Kestrel endpoint
Cấu hình endpoint cụ thể của Kestrel ghi đè tất cả các cấu hình endpoint cross-server. Cấu hình endpoint cross-server bao gồm:
UseUrls--urlstrên command line- Biến môi trường
ASPNETCORE_URLS
Xem xét phần cấu hình Kestrel sau trong file appsettings.json:
"Kestrel": {
"Endpoints": {
"Https": {
"Url": "https://localhost:9999"
}
}
},Trích xuất giá trị đơn từ cấu hình với type conversion (GetValue)
ConfigurationBinder.GetValue trích xuất giá trị đơn từ cấu hình với key được chỉ định và chuyển đổi nó sang type được chỉ định:
var number = Config.GetValue<int>("NumberKey", 99);Trong đoạn code trên:
ConfiglàIConfigurationđược inject.- Nếu
NumberKeykhông tìm thấy trong cấu hình, giá trị mặc định99được sử dụng.
Làm việc với sections (phần), lấy children của section và xác định section có tồn tại
Cho file subsection.json sau:
{
"section0": {
"key0": "value00",
"key1": "value01"
},
"section1": {
"key0": "value10",
"key1": "value11"
},
"section2": {
"subsection0": {
"key0": "value200",
"key1": "value201"
},
"subsection1": {
"key0": "value210",
"key1": "value211"
}
}
}GetSection
IConfiguration.GetSection trả về configuration subsection với subsection key được chỉ định:
var subsection = Config.GetSection("section1");
var value1 = subsection["key0"];
var value2 = subsection["key1"];GetSection không bao giờ trả về null. Nếu không tìm thấy section phù hợp, trả về IConfigurationSection rỗng.
GetChildren và Exists
var section = Config.GetSection("section2");
if (!section.Exists())
{
throw new Exception("section2 doesn't exist!");
}
var children = section.GetChildren();
foreach (var subSection in children)
{
int i = 0;
var key1 = subSection.Key + ":key" + i++.ToString();
var key2 = subSection.Key + ":key" + i.ToString();
Console.WriteLine($"{key1} value: {section[key1]}");
Console.WriteLine($"{key2} value: {section[key2]}");
}Bind an array (Bind mảng)
ConfigurationBinder.Bind hỗ trợ binding mảng với các đối tượng sử dụng array indices trong configuration keys:
{
"array": {
"entries": {
"0": "value00",
"1": "value10",
"2": "value20",
"4": "value40",
"5": "value50"
}
}
}public class ArrayExample
{
public string[]? Entries { get; set; }
}var array = Config.GetSection("array").Get<ArrayExample>();
if (array is null)
{
throw new ArgumentNullException(nameof(array));
}
for (int j = 0; j < array.Entries?.Length; j++)
{
Console.WriteLine($"Index: {j} Value: {array.Entries[j]}");
}Custom configuration provider (Nhà cung cấp cấu hình tùy chỉnh)
Ứng dụng mẫu thể hiện cách tạo basic configuration provider đọc các cặp key-value cấu hình từ database sử dụng Entity Framework (EF).
Định nghĩa entity EFConfigurationValue để lưu trữ các giá trị cấu hình trong database:
public class EFConfigurationValue
{
public string Id { get; set; } = string.Empty;
public string Value { get; set; } = string.Empty;
}Tạo custom configuration provider bằng cách kế thừa từ ConfigurationProvider:
public class EFConfigurationSource : IConfigurationSource
{
private readonly Action<DbContextOptionsBuilder> _optionsAction;
public EFConfigurationSource(Action<DbContextOptionsBuilder> optionsAction) =>
_optionsAction = optionsAction;
public IConfigurationProvider Build(IConfigurationBuilder builder) =>
new EFConfigurationProvider(_optionsAction);
}Extension method AddEFConfiguration cho phép thêm configuration source vào ConfigurationBuilder:
public static class EntityFrameworkExtensions
{
public static IConfigurationBuilder AddEFConfiguration(
this IConfigurationBuilder builder,
Action<DbContextOptionsBuilder> optionsAction)
{
return builder.Add(new EFConfigurationSource(optionsAction));
}
}Đoạn code sau cho thấy cách sử dụng EFConfigurationProvider tùy chỉnh trong file Program:
builder.Configuration.AddEFConfiguration(
opt => opt.UseInMemoryDatabase("InMemoryDb"));Thêm cấu hình từ external assembly
Implementation IHostingStartup cho phép thêm các enhancements vào ứng dụng khi khởi động từ external assembly bên ngoài class Startup của ứng dụng. Để biết thêm, xem Use hosting startup assemblies in ASP.NET Core.
Configuration-binding source generator
Configuration-binding source generator cung cấp cấu hình tương thích với AOT và trim. Để biết thêm, xem Configuration-binding source generator.