Trong bài viết này, chúng ta sẽ tìm hiểu cách cấu hình WebHostBuilder trong .NET 6.0, đặc biệt là cách sử dụng WebHostBuilderContext để truy cập thông tin cấu hình.
Khi đọc chương 4 "Sử dụng Kestrel để cấu hình và tùy chỉnh HTTPS", bạn có thể có một số câu hỏi:
- Làm thế nào để truyền mật khẩu vào cấu hình HTTPS bằng cơ chế mã hóa của người dùng?
- Bạn thậm chí có thể muốn biết liệu có thể lấy cấu hình từ Program.cs không?
Chúng ta sẽ giải quyết các câu hỏi trên bằng cách sử dụng WebHostBuilderContext.
Trong chương 4, chúng ta đã cấu hình WebHostBuilder Kestrel trong tệp Program.cs. Khi đó, chúng ta đã sử dụng bí mật người dùng (user secrets) để cấu hình mật khẩu chứng chỉ, như đoạn mã sau:
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.UseKestrel(options => {
options.Listen(IPAddress.Loopback, 5000);
options.Listen(IPAddress.Loopback, 5001, listenOptions => {
listenOptions.UseHttps("certificate.pfx", "topsecret");
});
}).UseStartup();
});
}
Đoạn mã này vẫn hiệu quả với .NET 5.0 và các phiên bản trước đó, và hầu hết các dự án web trong .NET 6.0. Tuy nhiên, nó không hiệu quả với các dự án web được tạo bằng mẫu dự án, ví dụ bạn có thể tạo dự án bằng lệnh sau:
dotnet new web -n HostBuilderConfig -o HostBuilderConfig
Tệp Program.cs trong mini API của .NET 6.0 trông như sau:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Cấu hình trong mini API trông như thế này:
using System.Net;
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseKestrel(options => {
options.Listen(IPAddress.Loopback, 5000);
options.Listen(IPAddress.Loopback, 5001, listenOptions => {
listenOptions.UseHttps("certificate.pfx", "topsecret");
});
});
Đoạn mã sau áp dụng cho tất cả các mẫu dự án trong .NET 6.0 và các phiên bản trước đó:
.UseKestrel((host, options) => {
// ...
})
Tham số đầu tiên host là một instance của WebHostBuilderContext, bạn có thể sử dụng nó để truy cập thông tin cấu hình.
builder.WebHost.UseKestrel((host, options) => {
var filename = host.Configuration.GetValue("AppSettings:certfilename", "");
var password = host.Configuration.GetValue("AppSettings:certpassword", "");
options.Listen(IPAddress.Loopback, 5000);
options.Listen(IPAddress.Loopback, 5001, listenOptions => {
listenOptions.UseHttps(filename, password);
});
});
Trong ví dụ này, chúng ta sử dụng dấu phân cách hai chấm để đọc giá trị từ tệp cấu hình JSON:
{
"AppSettings": {"certfilename": "certificate.pfx", "certpassword": "topsecret" },
"Logging": { "LogLevel": { "Default": "Warning"}},
"AllowedHosts": "*"
}
Lưu ý: Đây là ví dụ về cách đọc cấu hình từ JSON để cấu hình Kestrel. Hãy nhớ không lưu trữ bất kỳ thông tin xác thực (credentials) nào trong mã, mà thay vào đó hãy đọc từ kho lưu trữ bí mật người dùng. Cách sử dụng cụ thể có thể được thiết lập bằng cách thực thi lệnh .NET CLI sau trong thư mục dự án:
dotnet user-secrets init
dotnet user-secrets set "AppSettings:certfilename" "certificate.pfx"
dotnet user-secrets set "AppSettings:certpassword" "topsecret"
Điều này cũng áp dụng cho các biến môi trường:
SET APPSETTINGS_CERTFILENAME=certificate.pfx
SET APPSETTINGS_CERTPASSWORD=topsecret
Lưu ý: Vì kho lưu trữ bí mật người dùng chỉ được sử dụng cho phát triển cục bộ, nên nên truyền thông tin xác thực cho ứng dụng trong môi trường sản xuất hoặc môi trường tương tự sản xuất thông qua biến môi trường.
Quá trình này hoạt động như thế nào? Bạn có nhớ cách cấu hình trong Startup.cs của ASP.NET Core 1.0 không? Lúc đó chủ yếu là cấu hình trong hàm tạo của lớp StartUp, quy trình thêm thông tin xác thực người dùng tương tự, bạn có thể so sánh:
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
if (env.IsDevelopment()) {
builder.AddUserSecrets();
}
builder.AddEnvironmentVariables();
Configuration = builder.Build();
Đoạn mã này bây giờ được đóng gói trong phương thức CreateDefaultBuilder như sau:
builder.ConfigureAppConfiguration((hostingContext, config) => {
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
if (env.IsDevelopment()) {
var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));
if (appAssembly != null) {
config.AddUserSecrets(appAssembly, optional: true);
}
}
config.AddEnvironmentVariables();
if (args != null) { config.AddCommandLine(args); }
});
Chúng ta thấy mã không có nhiều thay đổi, Kestrel hỗ trợ cấu hình tệp appsettings.json hoặc sử dụng biến môi trường để chỉ định cổng, URL, v.v. Hãy xem mã trong WebHost.cs:
builder.UseKestrel((builderContext, options) => {
options.Configure(builderContext.Configuration.GetSection("Kestrel"));
})
Đoạn mã trên cấu hình Kestrel qua tệp appsettings.json:
"Kestrel": { "EndPoints": {"Http": { "Url": "http://localhost:5555" }} }
Hoặc, bạn có thể sử dụng biến môi trường sau để cấu hình:
SET KESTREL_ENDPOINTS_HTTP_URL=http://localhost:5555