Nguon: Microsoft Learn · .NET 8.0

Configuration (Cấu hình) trong ASP.NET Core

Nguồn: Configuration in 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:

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:

razor
@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:

csharp
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:

  1. Command-line arguments sử dụng Command-line Configuration Provider.
  2. Biến môi trường không có tiền tố ASPNETCORE_ hoặc DOTNET_ sử dụng Environment Variables Configuration Provider.
  3. User secrets khi ứng dụng chạy trong môi trường Development.
  4. File cấu hình ứng dụng theo môi trường thông qua appsettings.{ENVIRONMENT}.json.
  5. File cấu hình ứng dụng chung thông qua appsettings.json.
  6. 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):

  1. Command-line arguments sử dụng Command-line Configuration Provider.
  2. Biến môi trường có tiền tố DOTNET_ sử dụng Environment Variables Configuration Provider.
  3. 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:

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:

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:

csharp
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):

csharp
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):

csharp
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:

csharp
#if DEBUG
foreach (var c in app.Configuration.AsEnumerable())
{
    Console.WriteLine($"CONFIG: Key: {c.Key} Value: {c.Value}");
}
#endif

Configuration keys (Khóa cấu hình) và values (giá trị)

Configuration keys:

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:

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:DefaultConnectionConnectionStrings__DefaultConnection
Logging:LogLevel:DefaultLogging__LogLevel__Default
Logging:LogLevel:MicrosoftLogging__LogLevel__Microsoft
Logging:LogLevel:Microsoft.Hosting.LifetimeLogging__LogLevel__Microsoft.Hosting.Lifetime
AllowedHostsAllowedHosts

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.

ProviderCung cấp cấu hình từ…
Azure Key Vault Configuration ProviderAzure Key Vault
Azure App Configuration ProviderAzure App Configuration
Command-line Configuration ProviderCommand-line parameters
Custom configuration providerNguồn tùy chỉnh
Environment Variables Configuration ProviderBiến môi trường
File Configuration ProviderCác file INI, JSON và XML
Key-Per-File Configuration ProviderCác file trong thư mục
Memory Configuration ProviderCollections trong bộ nhớ
User secretsFile 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à:

  1. Cài đặt ứng dụng chung qua appsettings.json.
  2. Cài đặt ứng dụng theo môi trường qua appsettings.{ENVIRONMENT}.json.
  3. User secrets.
  4. Biến môi trường sử dụng Environment Variables Configuration Provider.
  5. 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:

json
{
  "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:

razor
@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:

  1. appsettings.json
  2. appsettings.{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ố:

csharp
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 stringProvider
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:

Command-line arguments

Lệnh dotnet run sau đây đặt keys và values sử dụng dấu bằng (=):

dotnetcli
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 (/):

dotnetcli
dotnet run /ConnectionStrings:DefaultConnection "Data Source=LocalSqlServer\\MSSQLDev;" /Logging:LogLevel:Default Information

Lệnh sau đặt keys và values sử dụng double dashes (--):

dotnetcli
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.

csharp
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:

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

IniConfigurationProvider tải cấu hình từ các cặp key-value trong file INI:

ini
[ConnectionStrings]
DefaultConnection="Data Source=LocalSqlServer\\MSSQLDev;"

[Logging:LogLevel]
Default=Debug
Microsoft=Debug
csharp
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:

csharp
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:

csharp
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.

csharp
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:

csharp
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:

Xem xét phần cấu hình Kestrel sau trong file appsettings.json:

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:

csharp
var number = Config.GetValue<int>("NumberKey", 99);

Trong đoạn code trên:

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:

json
{
  "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:

csharp
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.

GetChildrenExists

csharp
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:

json
{
  "array": {
    "entries": {
      "0": "value00",
      "1": "value10",
      "2": "value20",
      "4": "value40",
      "5": "value50"
    }
  }
}
csharp
public class ArrayExample
{
    public string[]? Entries { get; set; } 
}
csharp
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:

csharp
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:

csharp
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:

csharp
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:

csharp
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.