Có gì mới trong ASP.NET Core ở .NET 9
Bài viết này nêu bật những thay đổi quan trọng nhất trong ASP.NET Core ở .NET 9 kèm theo các liên kết tới tài liệu liên quan.
Tối ưu hóa phân phối tài nguyên tĩnh (Static asset delivery optimization)
MapStaticAssets routing endpoint conventions là tính năng mới tối ưu hóa việc phân phối tài nguyên tĩnh (static assets) trong các ứng dụng ASP.NET Core.
Việc áp dụng các phương pháp production tốt nhất để phục vụ tài nguyên tĩnh đòi hỏi nhiều công sức và chuyên môn kỹ thuật. Nếu không có các tối ưu hóa như nén (compression), bộ nhớ đệm (caching), và fingerprints:
- Trình duyệt phải thực hiện thêm các yêu cầu trong mỗi lần tải trang.
- Nhiều byte hơn mức cần thiết được truyền qua mạng.
- Đôi khi các phiên bản cũ của tệp được phục vụ cho client.
Tạo các ứng dụng web hiệu suất cao đòi hỏi phải tối ưu hóa việc phân phối tài nguyên đến trình duyệt. Các tối ưu hóa có thể bao gồm:
- Phục vụ một tài nguyên nhất định một lần cho đến khi tệp thay đổi hoặc trình duyệt xóa bộ nhớ cache. Đặt header ETag.
- Ngăn trình duyệt sử dụng tài nguyên cũ sau khi ứng dụng được cập nhật. Đặt header Last-Modified.
- Thiết lập các caching headers phù hợp.
- Sử dụng caching middleware.
- Phục vụ các phiên bản nén của tài nguyên khi có thể.
- Sử dụng CDN để phục vụ tài nguyên gần với người dùng hơn.
- Giảm thiểu kích thước tài nguyên phục vụ cho trình duyệt. Tối ưu hóa này không bao gồm minification (thu nhỏ).
MapStaticAssets là tính năng mới tối ưu hóa việc phân phối tài nguyên tĩnh trong ứng dụng. Nó được thiết kế để hoạt động với tất cả các UI framework (khung giao diện người dùng), bao gồm Blazor, Razor Pages và MVC. Thông thường đây là sự thay thế tương đương cho UseStaticFiles:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
+app.MapStaticAssets();
-app.UseStaticFiles();
app.MapRazorPages();
app.Run();MapStaticAssets hoạt động bằng cách kết hợp các quy trình tại thời điểm build và publish để thu thập thông tin về tất cả các tài nguyên tĩnh trong ứng dụng. Thông tin này sau đó được thư viện runtime sử dụng để phục vụ các tệp này một cách hiệu quả cho trình duyệt.
MapStaticAssets có thể thay thế UseStaticFiles trong hầu hết các trường hợp, tuy nhiên, nó được tối ưu hóa cho việc phục vụ các tài nguyên mà ứng dụng đã biết tại thời điểm build và publish. Nếu ứng dụng phục vụ tài nguyên từ các vị trí khác, chẳng hạn như đĩa hoặc embedded resources (tài nguyên nhúng), nên sử dụng UseStaticFiles.
MapStaticAssets cung cấp các lợi ích sau mà UseStaticFiles không có:
- Nén tại thời điểm build cho tất cả tài nguyên trong ứng dụng:
gziptrong quá trình phát triển vàgzip + brotlikhi publish.- Tất cả tài nguyên được nén với mục tiêu giảm kích thước xuống mức tối thiểu.
ETagsdựa trên nội dung: CácEtagcho mỗi tài nguyên là chuỗi mã hóa Base64 của hash SHA-256 của nội dung. Điều này đảm bảo trình duyệt chỉ tải lại tệp nếu nội dung của nó đã thay đổi.
Bảng sau đây cho thấy kích thước gốc và sau khi nén của các tệp CSS và JS trong template Razor Pages mặc định:
| Tệp | Gốc | Sau nén | % Giảm |
|---|---|---|---|
| bootstrap.min.css | 163 | 17.5 | 89.26% |
| jquery.js | 89.6 | 28 | 68.75% |
| bootstrap.min.js | 78.5 | 20 | 74.52% |
| Tổng | 331.1 | 65.5 | 80.20% |
Bảng sau đây cho thấy kích thước gốc và sau khi nén khi sử dụng thư viện Fluent UI Blazor components:
| Tệp | Gốc | Sau nén | % Giảm |
|---|---|---|---|
| fluent.js | 384 | 73 | 80.99% |
| fluent.css | 94 | 11 | 88.30% |
| Tổng | 478 | 84 | 82.43% |
Tổng cộng từ 478 KB chưa nén xuống còn 84 KB sau nén.
Tối ưu hóa diễn ra tự động khi sử dụng MapStaticAssets. Khi một thư viện được thêm vào hoặc cập nhật, chẳng hạn với JavaScript hoặc CSS mới, các tài nguyên được tối ưu hóa như một phần của quá trình build. Tối ưu hóa đặc biệt có lợi cho các môi trường di động có thể có băng thông thấp hơn hoặc kết nối không ổn định.
Bật nén động trên server so với sử dụng MapStaticAssets
MapStaticAssets có những ưu điểm sau so với nén động trên server:
- Đơn giản hơn vì không cần cấu hình riêng cho từng server.
- Hiệu suất cao hơn vì tài nguyên được nén tại thời điểm build.
- Cho phép nhà phát triển dành thêm thời gian trong quá trình build để đảm bảo tài nguyên có kích thước tối thiểu.
Blazor
Phần này mô tả các tính năng mới cho Blazor.
Template giải pháp .NET MAUI Blazor Hybrid và Web App
Một template giải pháp mới giúp dễ dàng tạo các ứng dụng client .NET MAUI native và Blazor web dùng chung UI. Template này cho thấy cách tạo các ứng dụng client tối đa hóa việc tái sử dụng code và hướng tới Android, iOS, Mac, Windows và Web.
Các tính năng chính của template này bao gồm:
- Khả năng chọn chế độ render (render mode) Blazor tương tác cho ứng dụng web.
- Tự động tạo các dự án phù hợp, bao gồm Blazor Web App (global Interactive Auto rendering) và ứng dụng .NET MAUI Blazor Hybrid.
- Các dự án được tạo sử dụng thư viện Razor class library (RCL) dùng chung để duy trì các Razor component trong UI.
- Code mẫu được bao gồm để minh họa cách sử dụng dependency injection (tiêm phụ thuộc) để cung cấp các triển khai giao diện khác nhau cho ứng dụng Blazor Hybrid và Blazor Web App.
Để bắt đầu, hãy cài đặt .NET 9 SDK và cài đặt .NET MAUI workload, chứa template:
dotnet workload install maui
Tạo giải pháp từ template dự án trong command shell bằng lệnh sau:
dotnet new maui-blazor-web
Template cũng có sẵn trong Visual Studio.
Phát hiện vị trí render, tính tương tác và chế độ render được chỉ định trong thời gian chạy
Chúng tôi đã giới thiệu một API mới được thiết kế để đơn giản hóa quá trình truy vấn trạng thái component trong thời gian chạy. API này cung cấp các khả năng sau:
- Xác định vị trí thực thi hiện tại của component: Điều này có thể hữu ích để gỡ lỗi và tối ưu hóa hiệu suất component.
- Kiểm tra xem component có đang chạy trong môi trường tương tác không: Điều này có thể hữu ích cho các component có hành vi khác nhau dựa trên tính tương tác của môi trường.
- Lấy chế độ render được chỉ định cho component: Hiểu chế độ render có thể giúp tối ưu hóa quá trình render và cải thiện hiệu suất tổng thể của component.
Cải thiện trải nghiệm kết nối lại phía server:
Những cải tiến sau đã được thực hiện cho trải nghiệm kết nối lại phía server mặc định:
- Khi người dùng điều hướng quay lại ứng dụng có circuit bị ngắt kết nối, việc kết nối lại được thử ngay lập tức thay vì chờ đến khoảng kết nối lại tiếp theo.
- Khi một lần thử kết nối lại đến server nhưng server đã giải phóng circuit, trang tự động làm mới.
- Thời gian kết nối lại sử dụng chiến lược backoff được tính toán. Theo mặc định, một vài lần thử kết nối lại đầu tiên xảy ra liên tiếp nhanh chóng mà không có khoảng thời gian thử lại trước khi các độ trễ được tính toán được đưa vào giữa các lần thử.
Blazor.start({
circuit: {
reconnectionOptions: {
retryIntervalMilliseconds: (previousAttempts, maxRetries) =>
previousAttempts >= maxRetries ? null : previousAttempts * 1000
},
},
});- Kiểu dáng của UI kết nối lại mặc định đã được hiện đại hóa.
Đơn giản hóa tuần tự hóa trạng thái xác thực cho Blazor Web Apps
Các API mới giúp dễ dàng hơn khi thêm xác thực vào Blazor Web App hiện có. Khi bạn tạo Blazor Web App mới với xác thực sử dụng Individual Accounts (tài khoản cá nhân) và bạn bật khả năng tương tác dựa trên WebAssembly, dự án bao gồm một AuthenticationStateProvider tùy chỉnh trong cả dự án server và client.
Bây giờ có các API, là một phần của template dự án Blazor Web App, có thể được gọi trong các dự án server và client để thêm chức năng này:
- AddAuthenticationStateSerialization: Thêm các dịch vụ cần thiết để tuần tự hóa trạng thái xác thực trên server.
- AddAuthenticationStateDeserialization: Thêm các dịch vụ cần thiết để giải tuần tự hóa trạng thái xác thực trong trình duyệt.
Thêm các trang static server-side rendering (SSR) vào Blazor Web App tương tác toàn cục
Với .NET 9, giờ đây đơn giản hơn để thêm các trang static SSR vào các ứng dụng áp dụng tính tương tác toàn cục.
Đánh dấu bất kỳ trang Razor component nào với thuộc tính [ExcludeFromInteractiveRouting] được gán bằng chỉ thị @attribute của Razor:
@attribute [ExcludeFromInteractiveRouting]
Constructor injection (tiêm thông qua constructor)
Razor component hỗ trợ constructor injection.
public partial class ConstructorInjection(NavigationManager navigation)
{
private void HandleClick()
{
navigation.NavigateTo("/counter");
}
}Nén WebSocket cho các Interactive Server component
Theo mặc định, Interactive Server component bật nén cho WebSocket connections và đặt chỉ thị frame-ancestors Content Security Policy (CSP - Chính sách bảo mật nội dung) thành 'self'.
Có thể tắt nén bằng cách đặt ConfigureWebSocketOptions thành null:
.AddInteractiveServerRenderMode(o => o.ConfigureWebSocketOptions = null)
Xử lý sự kiện keyboard composition trong Blazor
Thuộc tính KeyboardEventArgs.IsComposing mới cho biết liệu sự kiện bàn phím có phải là một phần của phiên composition hay không.
Thêm tham số OverscanCount vào QuickGrid
Component QuickGrid hiện hiển thị thuộc tính OverscanCount cho biết có bao nhiêu hàng bổ sung được render trước và sau vùng hiển thị khi bật ảo hóa (virtualization).
<QuickGrid ItemsProvider="itemsProvider" Virtualize="true" OverscanCount="4">
...
</QuickGrid>Component InputNumber hỗ trợ thuộc tính type="range"
Component InputNumber<TValue> hiện hỗ trợ thuộc tính type="range", tạo ra một range input hỗ trợ model binding và form validation.
Các sự kiện enhanced navigation mới
Kích hoạt callback JavaScript trước hoặc sau enhanced navigation với các event listener mới:
blazor.addEventListener("enhancednavigationstart", {CALLBACK})blazor.addEventListener("enhancednavigationend", {CALLBACK})
SignalR
Phần này mô tả các tính năng mới cho SignalR.
Hỗ trợ kiểu đa hình (Polymorphic type) trong SignalR Hubs
Các phương thức Hub giờ đây có thể chấp nhận lớp cơ sở thay vì lớp dẫn xuất để cho phép các kịch bản đa hình. Kiểu cơ sở cần được chú thích để cho phép đa hình.
public class MyHub : Hub
{
public void Method(JsonPerson person)
{
if (person is JsonPersonExtended)
{
}
else if (person is JsonPersonExtended2)
{
}
else
{
}
}
}
[JsonPolymorphic]
[JsonDerivedType(typeof(JsonPersonExtended), nameof(JsonPersonExtended))]
[JsonDerivedType(typeof(JsonPersonExtended2), nameof(JsonPersonExtended2))]
private class JsonPerson
{
public string Name { get; set; }
public Person Child { get; set; }
public Person Parent { get; set; }
}
private class JsonPersonExtended : JsonPerson
{
public int Age { get; set; }
}
private class JsonPersonExtended2 : JsonPerson
{
public string Location { get; set; }
}Cải tiến Activities cho SignalR
SignalR giờ đây có ActivitySource cho cả hub server và client.
.NET SignalR server ActivitySource
ActivitySource SignalR có tên Microsoft.AspNetCore.SignalR.Server phát ra các sự kiện cho các lời gọi phương thức hub.
.NET SignalR client ActivitySource
ActivitySource SignalR có tên Microsoft.AspNetCore.SignalR.Client phát ra các sự kiện cho SignalR client.
Hub invocations trên client và server hỗ trợ context propagation. Việc truyền trace context cho phép distributed tracing (theo dõi phân tán) thực sự.
SignalR hỗ trợ trimming và Native AOT
Tiếp tục hành trình Native AOT bắt đầu từ .NET 8, chúng tôi đã bật hỗ trợ trimming (cắt tỉa) và native ahead-of-time (AOT) compilation cho cả các kịch bản SignalR client và server.
using Microsoft.AspNetCore.SignalR;
using System.Text.Json.Serialization;
var builder = WebApplication.CreateSlimBuilder(args);
builder.Services.AddSignalR();
builder.Services.Configure<JsonHubProtocolOptions>(o =>
{
o.PayloadSerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonSerializerContext.Default);
});
var app = builder.Build();
app.MapHub<ChatHub>("/chatHub");
// ...
[JsonSerializable(typeof(string))]
internal partial class AppJsonSerializerContext : JsonSerializerContext { }
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
}Giới hạn
- Hiện tại chỉ hỗ trợ JSON protocol.
- Trên SignalR server, các tham số phương thức Hub kiểu
IAsyncEnumerable<T>vàChannelReader<T>trong đóTlà ValueType (struct) không được hỗ trợ. - Strongly typed hubs không được hỗ trợ với Native AOT (
PublishAot). - Chỉ
Task,Task<T>,ValueTaskhoặcValueTask<T>được hỗ trợ cho các kiểu trả về async.
Minimal APIs
Phần này mô tả các tính năng mới cho Minimal APIs.
Thêm InternalServerError và InternalServerError<TValue> vào TypedResults
Lớp TypedResults hiện bao gồm các factory method và kiểu để trả về phản hồi "500 Internal Server Error":
var app = WebApplication.Create();
app.MapGet("/", () => TypedResults.InternalServerError("Something went wrong!"));
app.Run();Gọi ProducesProblem và ProducesValidationProblem trên các route group
var app = WebApplication.Create();
var todos = app.MapGroup("/todos")
.ProducesProblem();
todos.MapGet("/", () => new Todo(1, "Create sample app", false));
todos.MapPost("/", (Todo todo) => Results.Ok(todo));
app.Run();
record Todo(int Id, string Title, boolean IsCompleted);Kiểu kết quả Problem và ValidationProblem hỗ trợ khởi tạo với giá trị IEnumerable<KeyValuePair<string, object?>>
var app = WebApplication.Create();
app.MapGet("/", () =>
{
var extensions = new List<KeyValuePair<string, object?>> { new("test", "value") };
return TypedResults.Problem("This is an error with extensions",
extensions: extensions);
});OpenAPI
Phần này mô tả các tính năng mới cho OpenAPI.
Hỗ trợ tích hợp để tạo tài liệu OpenAPI
Đặc tả OpenAPI là một tiêu chuẩn để mô tả các HTTP API. Trong .NET 9, ASP.NET Core cung cấp hỗ trợ tích hợp để tạo tài liệu OpenAPI thông qua gói Microsoft.AspNetCore.OpenApi.
var builder = WebApplication.CreateBuilder();
builder.Services.AddOpenApi();
var app = builder.Build();
app.MapOpenApi();
app.MapGet("/hello/{name}", (string name) => $"Hello {name}"!);
app.Run();Microsoft.AspNetCore.OpenApi hỗ trợ trimming và Native AOT
OpenAPI trong ASP.NET Core hỗ trợ trimming và native AOT.
Xác thực và phân quyền (Authentication and authorization)
Phần này mô tả các tính năng mới cho xác thực và phân quyền.
OpenIdConnectHandler thêm hỗ trợ Pushed Authorization Requests (PAR)
Pushed Authorization Requests (PAR) là một tiêu chuẩn OAuth tương đối mới cải thiện bảo mật của các luồng OAuth và OIDC bằng cách chuyển các tham số ủy quyền từ front channel sang back channel.
Đối với .NET 9, PAR được bật theo mặc định nếu tài liệu discovery của identity provider quảng cáo hỗ trợ PAR. Nếu điều này gây ra sự cố, bạn có thể tắt PAR qua OpenIdConnectOptions.PushedAuthorizationBehavior:
builder.Services
.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect("oidc", oidcOptions =>
{
oidcOptions.PushedAuthorizationBehavior = PushedAuthorizationBehavior.Disable;
});Tùy chỉnh tham số OIDC và OAuth
Các handler xác thực OAuth và OIDC giờ đây có tùy chọn AdditionalAuthorizationParameters để dễ dàng tùy chỉnh các tham số tin nhắn ủy quyền:
builder.Services.AddAuthentication().AddOpenIdConnect(options =>
{
options.AdditionalAuthorizationParameters.Add("prompt", "login");
options.AdditionalAuthorizationParameters.Add("audience", "https://api.example.com");
});Cấu hình cờ xác thực mở rộng HTTP.sys
Bây giờ bạn có thể cấu hình các cờ HTTP.sys HTTP_AUTH_EX_FLAG_ENABLE_KERBEROS_CREDENTIAL_CACHING và HTTP_AUTH_EX_FLAG_CAPTURE_CREDENTIAL bằng cách sử dụng các thuộc tính EnableKerberosCredentialCaching và CaptureCredentials mới:
webBuilder.UseHttpSys(options =>
{
options.Authentication.Schemes = AuthenticationSchemes.Negotiate;
options.Authentication.EnableKerberosCredentialCaching = true;
options.Authentication.CaptureCredentials = true;
});Các tính năng khác
Thư viện HybridCache mới
HybridCache hiện vẫn đang trong preview nhưng sẽ được phát hành đầy đủ sau .NET 9 trong một bản phát hành minor tương lai của .NET Extensions.
API HybridCache lấp đầy một số khoảng trống trong các API IDistributedCache và IMemoryCache hiện có. Nó cũng thêm các khả năng mới, chẳng hạn như:
- Bảo vệ "Stampede" để ngăn các lần tìm nạp song song cùng một công việc.
- Tuần tự hóa có thể cấu hình.
public class SomeService(HybridCache cache)
{
public async Task<SomeInformation> GetSomeInformationAsync
(string name, int id, CancellationToken token = default)
{
return await cache.GetOrCreateAsync(
$"someinfo:{name}:{id}",
async cancel => await SomeExpensiveOperationAsync(name, id, cancel),
token: token
);
}
}Cải tiến trang developer exception (trang ngoại lệ nhà phát triển)
Trang developer exception của ASP.NET Core được hiển thị khi ứng dụng ném ra ngoại lệ chưa được xử lý trong quá trình phát triển.
Preview 3 đã thêm endpoint metadata vào trang developer exception. Các cải tiến nhỏ về chất lượng cuộc sống được phát hiện trong Preview 4:
- Gói văn bản tốt hơn. Cookies dài, giá trị chuỗi truy vấn và tên phương thức không còn thêm thanh cuộn ngang của trình duyệt nữa.
- Văn bản lớn hơn theo phong cách thiết kế hiện đại.
- Kích thước bảng nhất quán hơn.
Cải tiến gỡ lỗi Dictionary
Màn hình gỡ lỗi của dictionary (từ điển) và các collection key-value khác có bố cục được cải thiện. Key được hiển thị trong cột key của debugger thay vì được nối với value.
Sửa lỗi 503 trong quá trình recycle ứng dụng trong IIS
Theo mặc định giờ có độ trễ 1 giây giữa khi IIS được thông báo về recycle hoặc shutdown và khi ANCM yêu cầu managed server bắt đầu shutdown.
<aspNetCore processPath="dotnet" arguments="myapp.dll" stdoutLogEnabled="false" stdoutLogFile=".logsstdout">
<handlerSettings>
<handlerSetting name="shutdownDelay" value="5000" />
</handlerSettings>
</aspNetCore>ASP0026: Analyzer cảnh báo khi [Authorize] bị ghi đè bởi [AllowAnonymous] từ "xa hơn"
Trong .NET 9 Preview 6, chúng tôi đã giới thiệu một analyzer sẽ đánh dấu các trường hợp trong đó một thuộc tính [Authorize] gần hơn bị ghi đè bởi thuộc tính [AllowAnonymous] xa hơn từ một MVC action.
ASP0026 [Authorize] overridden by [AllowAnonymous] from farther away
Cải thiện Kestrel connection metrics
Chúng tôi đã thực hiện cải tiến đáng kể cho connection metrics của Kestrel bằng cách bao gồm metadata về lý do kết nối thất bại. Metric kestrel.connection.duration giờ đây bao gồm lý do đóng kết nối trong thuộc tính error.type.
Tùy chỉnh Kestrel named pipe endpoints
Hỗ trợ named pipe (đường ống có tên) của Kestrel đã được cải thiện với các tùy chọn tùy chỉnh nâng cao. Phương thức CreateNamedPipeServerStream mới trên named pipe options cho phép pipe được tùy chỉnh theo từng endpoint.
Tùy chọn ExceptionHandlerMiddleware để chọn status code dựa trên kiểu ngoại lệ
app.UseExceptionHandler(new ExceptionHandlerOptions
{
StatusCodeSelector = ex => ex is TimeoutException
? StatusCodes.Status503ServiceUnavailable
: StatusCodes.Status500InternalServerError,
});Opt-out khỏi HTTP metrics trên các endpoint và yêu cầu nhất định
.NET 9 giới thiệu khả năng opt-out (không tham gia) khỏi HTTP metrics cho các endpoint và yêu cầu cụ thể:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHealthChecks();
var app = builder.Build();
app.MapHealthChecks("/healthz").DisableHttpMetrics();
app.Run();Data Protection hỗ trợ xóa key (khóa)
Trước .NET 9, data protection keys (khóa bảo vệ dữ liệu) không thể xóa theo thiết kế, để ngăn mất dữ liệu. Trong .NET 9, chúng tôi đã giới thiệu tùy chọn để xóa keys.
if (keyManager is IDeletableKeyManager deletableKeyManager)
{
var utcNow = DateTimeOffset.UtcNow;
var yearAgo = utcNow.AddYears(-1);
if (!deletableKeyManager.DeleteKeys(key => key.ExpirationDate < yearAgo))
{
Console.WriteLine("Failed to delete keys.");
}
else
{
Console.WriteLine("Old keys deleted successfully.");
}
}Middleware hỗ trợ Keyed DI
Middleware giờ đây hỗ trợ Keyed DI trong cả constructor và phương thức Invoke/InvokeAsync:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddKeyedSingleton<MySingletonClass>("test");
builder.Services.AddKeyedScoped<MyScopedClass>("test2");
var app = builder.Build();
app.UseMiddleware<MyMiddleware>();
app.Run();
internal class MyMiddleware
{
private readonly RequestDelegate _next;
public MyMiddleware(RequestDelegate next,
[FromKeyedServices("test")] MySingletonClass service)
{
_next = next;
}
public Task Invoke(HttpContext context,
[FromKeyedServices("test2")]
MyScopedClass scopedService) => _next(context);
}Tin tưởng chứng chỉ HTTPS phát triển ASP.NET Core trên Linux
Trên các distro Linux dựa trên Ubuntu và Fedora, dotnet dev-certs https --trust giờ đây cấu hình chứng chỉ HTTPS phát triển ASP.NET Core là chứng chỉ đáng tin cậy cho:
- Các trình duyệt Chromium, ví dụ: Google Chrome, Microsoft Edge và Chromium.
- Mozilla Firefox và các trình duyệt dẫn xuất từ Mozilla.
- Các .NET APIs, ví dụ: HttpClient.
Templates được cập nhật lên Bootstrap, jQuery và jQuery Validation phiên bản mới nhất
Các template dự án ASP.NET Core và thư viện đã được cập nhật để sử dụng các phiên bản mới nhất:
- Bootstrap 5.3.3
- jQuery 3.7.1
- jQuery Validation 1.21.0
Breaking changes (Thay đổi vi phạm)
Sử dụng các bài viết trong Breaking changes in .NET để tìm các thay đổi vi phạm có thể áp dụng khi nâng cấp ứng dụng lên phiên bản .NET mới hơn.