Tác giả: Khalid Abuhakmeh | Ngày 04 tháng 11 năm 2025
Làn gió của sự thay đổi đang thổi về phía .NET 10, và nhiều đội nhóm đang điều chỉnh cánh buồm của mình để dấn thân vào những cuộc phiêu lưu mới mẻ và táo bạo. Một thời điểm thú vị đang ở phía trước. Vì .NET 10 đánh dấu phiên bản hỗ trợ dài hạn (LTS) của SDK và runtime, đây là lúc tuyệt vời để lên kế hoạch và xây dựng chiến lược. Xét cho cùng, chúng ta đều có nguồn lực, vòng lặp phát triển và năng lượng hạn chế khi nâng cấp. Bạn không muốn con tàu của mình gặp phải những vùng nước động bất ngờ.
Trong bài viết này, Duende đã xem xét các thay đổi gây hại của .NET 10 hiện đang được ghi nhận và tìm ra một số mục bạn cần lưu ý khi nâng cấp. Hy vọng rằng, phần lớn những mục này sẽ không gây rắc rối trong quá trình nâng cấp của bạn, nhưng một số có thể khiến bạn mắc kẹt trên một hòn đảo hoang mang tên là “thất vọng”. Không theo thứ tự cụ thể, hãy cùng xem chúng là gì và tại sao bạn nên đánh dấu chúng trên bản đồ nâng cấp của mình.
Mục lục
Chuyển Hướng Đăng Nhập Cookie Bị Tắt Đối Với Các Endpoint API Đã Biết
Pipeline của ASP.NET Core có thể cấu hình để đáp ứng nhiều nhu cầu đa dạng. Nhiều khách hàng Duende của chúng tôi kết hợp các API endpoint được bảo mật bằng OAuth cùng với giao diện ASP.NET Core MVC hoặc Razor Pages. Điều tự nhiên là nhiều nhà phát triển .NET sẽ nhận thấy một hành vi điển hình: các API endpoint của họ vô tình kích hoạt phản hồi thách thức (challenge response), cố gắng chuyển hướng người gọi đến phiên bản Duende IdentityServer. Hành vi chuyển hướng này thường không phải là điều hầu hết các nhà phát triển mong muốn. Người gọi có khả năng sẽ muốn thấy phản hồi 401 Unauthorized hoặc 403 Forbidden – xét cho cùng thì đó là một API!
Trong .NET 10, bất kỳ endpoint nào được bảo mật bằng xác thực cookie và được đánh dấu bằng giao diện IApiEndpointMetadata sẽ không còn chuyển hướng đến URI đăng nhập hoặc từ chối truy cập nữa. Thay đổi này bao gồm các endpoint ApiController, các endpoint Minimal API xử lý yêu cầu JSON đến hoặc phản hồi JSON đi, các endpoint sử dụng TypedResults, hoặc các endpoint SignalR.
Mặc dù hầu hết khách hàng của Duende sẽ hoan nghênh thay đổi này, nhưng nó vẫn là một sự sai lệch về hành vi so với trước đây. Nói cách khác, thay đổi này có thể ảnh hưởng đến các triển khai đã tồn tại. Hãy lưu ý đến thay đổi này và kiểm tra phù hợp khi nâng cấp.
IActionContextAccessor Và ActionContextAccessor Đã Bị Đánh Dấu Lỗi Thời (Obsolete)
.NET hiện đánh dấu các abstraction IActionContextAccessor và ActionContextAccessor là lỗi thời. Mặc dù không được sử dụng trực tiếp trong Duende IdentityServer, một số khách hàng có thể sử dụng các abstraction này trong các tùy chỉnh cho triển khai của họ.
Vì ASP.NET Core đã chuyển sang Endpoint Routing, bạn có thể thay thế bất kỳ sử dụng nào của IActionContextAccessor bằng HttpContextAccessor hoặc IHttpContextAccessor.
public class MyService
{
private readonly IHttpContextAccessor _httpContextAccessor;
public MyService(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public void DoSomething()
{
var httpContext = _httpContextAccessor.HttpContext;
var endpoint = httpContext?.GetEndpoint();
var actionDescriptor = endpoint?.Metadata.GetMetadata<ActionDescriptor>();
// Sử dụng metadata của action descriptor
}
}
Lưu ý rằng HttpContext vẫn chỉ có sẵn trong vòng đời của một yêu cầu web đang hoạt động.
IPNetwork Và ForwardedHeadersOptions.KnownNetworks Đã Bị Đánh Dấu Lỗi Thời
Nhiều khách hàng của Duende, đặc biệt là những người sử dụng phiên bản Enterprise, phụ thuộc nhiều vào Forwarded Headers để triển khai các giải pháp bảo mật cân bằng tải. Điều này yêu cầu cấu hình ứng dụng ASP.NET Core phù hợp. Cấu hình liên quan đến việc thiết lập ForwardedHeadersMiddlware và các tùy chọn của nó.
Trong .NET 10, khi sử dụng KnownNetworks trong ForwardHeaderOptions, bạn sẽ bắt đầu nhận được cảnh báo lỗi thời, hướng dẫn bạn sử dụng KnownIpNetworks để thay thế.
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
KnownIpNetworks.Add(new(IPAddress.Loopback, 8))
});
Với Duende IdentityServer, bạn có thể sử dụng tài liệu discovery để xác minh rằng các forward headers được thiết lập và xử lý chính xác trong môi trường staging.
Biên Dịch Run-Time Razor Đã Bị Đánh Dấu Lỗi Thời
Một nhà phát triển có thể sử dụng tính năng biên dịch run-time Razor để tạo vòng lặp phản hồi nhanh hơn. Trước đây, tính năng này sẽ biên dịch lại các tệp .cshtml đã thay đổi trong thời gian chạy. Kỹ thuật này tránh được giai đoạn khởi động lại thường chậm. .NET hiện đánh dấu phương thức AddRazorRuntimeCompilation là lỗi thời để chuyển sang Hot Reload dựa trên công cụ, mà các nhà phát triển có thể tìm thấy trong Visual Studio, C# Dev Kit cho VS Code và JetBrains Rider.
Nếu bạn tiếp tục sử dụng tính năng này, bạn sẽ thấy thông báo cảnh báo sau đây.
warning ASPDEPR003: Razor run-time compilation is obsolete and is not recommended for production scenarios.
For production scenarios, use the default build time compilation. For development scenarios, use Hot Reload instead.
For more information, visit https://aka.ms/aspnet/deprecate/003.
Các nhà phát triển coi cảnh báo như lỗi có thể thấy bản dựng của họ thất bại cho đến khi họ giải quyết được vấn đề cụ thể này. Mặc dù chúng tôi không sử dụng biên dịch run-time Razor trong các template của mình, nhưng chúng tôi có thể hình dung các nhà phát triển có thể đã thêm nó để cải thiện quy trình làm việc của họ.
WebHostBuilder, IWebHost Và WebHost Đã Bị Đánh Dấu Lỗi Thời
Điều này ảnh hưởng đến chúng tôi nhiều nhất, vì mã nguồn của Duende sử dụng WebHostBuilder trong toàn bộ codebase và bộ kiểm thử. Đừng lo lắng. Chúng tôi hiện đang hiện đại hóa và sẽ sẵn sàng cho .NET 10. Tuy nhiên, nếu bạn có một triển khai Duende IdentityServer hiện tại dựa trên các template cũ, bạn sẽ cần điều chỉnh mã một chút để tránh các cảnh báo này.
warning ASPDEPR004: WebHostBuilder is deprecated in favor of HostBuilder and WebApplicationBuilder.
For more information, visit https://aka.ms/aspnet/deprecate/004.
Như thông báo đã lưu ý, bạn sẽ cần chuyển từ WebHostBuilder sang HostBuilder hoặc WebApplicationBuilder. Nếu bạn đang inject IWebHost như một dependency, hãy cân nhắc chuyển sang IHost hoặc tạo một abstraction có mục tiêu để truyền thông tin cần thiết.
Hình Ảnh Container .NET Mặc Định Hiện Sử Dụng Ubuntu
Đối với các phiên bản trước, đội ngũ .NET đã xây dựng các hình ảnh container dựa trên Debian. Bắt đầu từ .NET 10, đội ngũ .NET đã chuyển sang Ubuntu làm hình ảnh cơ sở. Lý do cho sự thay đổi này là Ubuntu có chu kỳ hỗ trợ dài hơn, nghĩa là phiên bản .NET trong container sẽ không được hỗ trợ trước khi bản phân phối Linux lưu trữ ứng dụng của bạn. Khó có thể có bất kỳ khác biệt đáng chú ý nào, nhưng phòng bệnh hơn chữa bệnh.
Giới Hạn Độ Dài URI Đã Được Loại Bỏ Khi Tạo Phiên Bản Mới
Thay đổi đối với giới hạn độ dài Uri nhìn chung có thể là một điều tốt cho các nhà phát triển, nhưng nó cũng có thể gây ra nhiều vấn đề runtime hơn. Bắt đầu từ .NET 10, sẽ không còn ngoại lệ runtime nào được đưa ra khi bạn tạo một Uri có hơn 65.000 ký tự.
new Uri($"https://host/{new string('a', 100_000)}")
Mặc dù giờ đây bạn có thể tạo các phiên bản Uri lớn, máy chủ đích phải có khả năng chấp nhận các payload lớn này. Nếu không, hãy chuẩn bị tinh thần cho các ngoại lệ. Hãy sử dụng lẽ thường và khả năng phán đoán nhé.
Tham Số Khóa Của X509Certificate Và PublicKey Có Thể Là Null
Một thay đổi nhỏ đối với hành vi của lớp X509Certificate có thể gây ra các ngoại lệ runtime mà bạn nên chú ý.
Các lớp
X509Certificate,X509Certificate2vàPublicKeyhiển thị thông tin về Subject Public Key Info. Một trong các thuộc tính của Subject Public Key Info là các tham số cho thuật toán. Subject Public Key Info không bắt buộc phải chứa các tham số thuật toán. Trước đây, điều này được biểu diễn dưới dạng một mảng byte rỗng, không phải ASN.1 hợp lệ. Cố gắng mã hóa hoặc giải mã nó sẽ gây ra ngoại lệ. Để biểu diễn rõ ràng hơn các tham số khóa vắng mặt,nullhiện được trả về và các thành viên trả về tham số thuật toán đã được chú thích để trả về các giá trị nullable.
Khi làm việc với chứng chỉ, hãy nhớ lập trình phòng thủ và kiểm tra xem kết quả có khác null hay không.
byte[] parameters = certificate.GetKeyAlgorithmParameters();
if (parameters == null)
{
// Xử lý trường hợp không có tham số thuật toán
}
Khi làm việc với Duende IdentityServer, chúng tôi có một vài khách hàng xử lý các phiên bản X509Certificate trong mã kết hợp với Duende IdentityModel. Đây là thời điểm tốt để quay lại và xác minh các kiểm tra nullable thích hợp đã được bật và tuân theo.
Kết Luận
.NET 10 là thời điểm tuyệt vời để nâng cấp ứng dụng và các dependency của bạn, vì sự thay đổi có thể mang lại hiệu suất ứng dụng được cải thiện và các tính năng nâng cao. Mặc dù điều này rất thú vị, nhưng bạn nên tiến hành một cách thận trọng. Với một chút thông tin, giờ đây bạn có thể nâng cấp các giải pháp định danh (identity) của mình một cách tự tin.
Hãy cho chúng tôi biết trong phần bình luận nếu bạn đang lên kế hoạch nâng cấp lên .NET 10, hoặc có thể bạn đã làm điều đó và muốn chia sẻ kinh nghiệm của mình với những người khác. Nếu bạn đang trong quá trình nâng cấp, hãy tham gia cộng đồng thảo luận Duende và để chúng tôi giúp đỡ bằng cách trả lời các câu hỏi.



