原文:《ASP.NET Core updates in .NET 6 Preview 2》,作者 Daniel Roth
.NET 6 預覽版 2 現已推出,其中包括許多對 ASP.NET Core 的新改進。
以下是本次預覽版的新內容:
- Razor 編譯器更新為使用 Source Generators
- Blazor 支持自定義事件參數
- 增加 MVC 視圖和 Razor 頁面的 CSS 隔離
- Blazor 支持從祖先組件中推斷組件的泛型類型
- Blazor 應用程序支持保留預渲染時的狀態
- SignalR – 支持 Nullable 標注
馬上開始
想開始在 .NET 6 Preview 2 中使用 ASP.NET Core,請先安裝 .NET 6 SDK。
如果您正在 Windows 上使用 Visual Studio,我們建議安裝 Visual Studio 2019 16.10 的最新預覽版。如果您在 macOS 上,我們建議安裝 Visual Studio 2019 for Mac 8.10 的最新預覽版。
升級現有項目
要將現有的 ASP.NET Core 應用程序從 .NET 6 Preview 1升級到.NET 6 Preview 2,您需要:
- 更新所有 Microsoft.AspNetCore.* 包的引用到 6.0.0-preview.2.*.
- 更新所有 Microsoft.Extensions.* 包的引用到 6.0.0-preview.2.*.
再查看完整的 ASP.NET Core 在 .NET 6 中的破壞性改動列表。
Razor 編譯器更新為使用 Source Generators
我們在這個預覽版中更新了 Razor 編譯器,使用 C# Source Generators來實現。Source Generators 在編譯過程中運行,並能檢查正在編譯的內容,以生成額外的文件,與項目的其余部分一起編譯。我們使用 Source Generators 簡化了 Razor 編譯器,並顯著加快了構建的時間。
下圖顯示了使用新的 Razor 編譯器構建默認的 Blazor Server 和 MVC 模板時的構建時間改進。
Blazor 支持自定義事件參數
Blazor 對自定義事件的支持現已擴展到支持自定義事件參數。這允許通過自定義事件向 .NET 事件處理程序傳遞任意數據。
例如,您可能希望在用戶粘貼文本的同時接收剪貼板粘貼事件。要做到這一點,首先要為您的事件聲明一個自定義的名稱,以及一個 .NET ,該類將持有該事件的事件參數,通過添加以下類到您的項目中:
[EventHandler("oncustompaste", typeof(CustomPasteEventArgs), enableStopPropagation: true, enablePreventDefault: true)]
public static class EventHandlers
{
// 這個靜態類不需要包含任何成員。
// 它只是一個讓我們可以把 [EventHandler] 屬性放在 Razor 編譯器上配置事件類型的地方。
// 這樣將影響編譯器的輸出以及編輯器中的代碼完成。
}
public class CustomPasteEventArgs : EventArgs
{
// 這些屬性的數據將由自定義的 JavaScript 邏輯提供。
public DateTime EventTimestamp { get; set; }
public string PastedData { get; set; }
}
一旦這些都到位了,您就會在您的 Razor 組件中得到一個叫做 @oncustompaste
的新事件的智能提醒。例如,在 Index.razor
中,您可以按以下方式使用它:
@page "/"
<p>Try pasting into the following text box:</p>
<input @oncustompaste="HandleCustomPaste" />
<p>@message</p>
@code {
string message;
void HandleCustomPaste(CustomPasteEventArgs eventArgs)
{
message = $"At {eventArgs.EventTimestamp.ToShortTimeString()}, you pasted: {eventArgs.PastedData}";
}
}
然而,如果您現在實際運行代碼,事件將不會觸發。因為還剩下一個步驟,就是添加一些 JavaScript 代碼,實際為您的新 EventArgs
子類提供數據。在您的 index.html
或 _Host.cshtml
文件中,添加以下內容:
<!-- 您需要將這段代碼直接添加到 blazor.server.js 或 blazor.webassembly.js 的 <script> 標簽后面。-->
<script>
Blazor.registerCustomEventType('custompaste', {
browserEventName: 'paste',
createEventArgs: event => {
// 這個例子只處理粘貼文本,但你可以使用任意的 JavaScript API
// 來處理用戶粘貼其他類型的數據,如圖片。
return {
eventTimestamp: new Date(),
pastedData: event.clipboardData.getData('text')
};
}
});
</script>
這是告訴瀏覽器,每當本地粘貼事件發生時,它也應該引發一個自定義粘貼事件,並使用您的自定義邏輯提供事件參數數據。請注意,事件名稱的約定在 .NET(事件名稱前綴為on)和 JavaScript(事件名稱沒有任何前綴)之間有所不同。
增加 MVC 視圖和 Razor 頁面的 CSS 隔離
現在,MVC視圖 和 Razor 頁面跟 Blazor 組件一樣支持 CSS 隔離。想要添加一個視圖或頁面特定的 CSS 文件,只需添加一個與 .cshtml
文件名稱相匹配的 .cshtml.css
文件即可。
Index.cshtml.css
h1 {
color: red;
}
在你的布局中添加一個鏈接到 {項目名}.styles.css 來引用捆綁的樣式。
<link rel="stylesheet" href="MyWebApp.styles.css" />
然后,這些樣式將只應用於各自的視圖和頁面。
Blazor 支持從祖先組件中推斷組件的泛型類型
在使用 Blazor 的泛型組件(如 Grid<TItem>
或 ListView<TItem>
)時,Blazor 通常可以根據傳遞給組件的參數來推斷泛型類型參數,因此您不必明確指定它們。但在更復雜的組件中,您可能會有多個泛型組件一起使用,而這些組件的類型參數是要匹配的,比如 Grid<TItem>
和 Column<TItem>
。在這些復合場景中,泛型類型參數通常需要顯式指定,就像這樣:
<Grid Items="@people">
<Column TItem="Person" Name="Full name">@context.FirstName @context.LastName</Column>
<Column TItem="Person" Name="E-mail address">@context.Email</Column>
</Grid>
但你真正想做的是:
<Grid Items="@people">
<Column Name="Full name">@context.FirstName @context.LastName</Column>
<Column Name="E-mail address">@context.Email</Column>
</Grid>
有必要在每個 <Column>
上重新指定 TItem
,因為每個 <Column>
都被視為一個獨立的組件,沒有其他方法知道它應該與什么類型的數據一起工作。
在 .NET 6 Preview 2 中,Blazor 可以從祖先組件中推斷出泛型類型參數。祖先組件必須選擇性地加入這種行為,使用 [CascadingTypeParameter]
特性(attribute)來通過名稱將類型參數級聯到后代。這個特性(attribute)允許泛型類型推斷出,對於有同名類型參數的子代,可以自動使用指定的類型參數。
例如,你可以定義像這樣的 Grid
和 Column
組件:
Grid.razor
@typeparam TItem
@attribute [CascadingTypeParameter(nameof(TItem))]
...
@code {
[Parameter] public IEnumerable<TItem> Items { get; set; }
[Parameter] public RenderFragment ChildContent { get; set; }
}
Column.razor
@typeparam TItem
...
@code {
[Parameter] public string Title { get; set; }
}
然后你可以像這樣使用 Grid
和 Column
組件:
<Grid Items="@GetItems()">
<Column Title="Product name" />
<Column Title="Num sales" />
</Grid>
@code {
IEnumerable<SaleRecord> GetItems() { ... }
}
注意:Visual Studio Code 中的 Razor 支持尚未更新以支持該功能,因此即使項目正確構建,你也可能遇到誤判的錯誤提醒。這將在即將發布的工具版本中解決。
Blazor 應用程序支持保留預渲染時的狀態
Blazor 應用程序可從服務端進行預渲染,以加快應用程序可感知的加載時間。當應用程序在后台進行交互性設置時,可立即渲染預渲染的 HTML。但是,預渲染期間使用的任何狀態都會丟失,必須在應用程序完全加載時重新創建。如果異步設置任何狀態,那么當預渲染的 UI 被臨時占位符替換,然后再次完全渲染時,UI可能會閃爍。
為了解決這個問題,我們增加了新的 <preserve-component-state />
tag helper,它可以支持把狀態持久化到預渲染頁面。在你的應用程序中,你可以使用新的 ComponentApplicationState
服務來決定你要持久化的狀態。當狀態即將被持久化到預渲染頁面中時,ComponentApplicationState.OnPersisting
事件會被觸發。然后你就可以在初始化你的組件時恢復(retrieved)任何已被持久化的狀態。
下面的示例展示了如何在預渲染期間持久化默認的 FetchData
組件中的天氣預報,然后在 Blazor
服務端應用程序中恢復狀態以初始化該組件。
_Host.cshtml
<body>
<component type="typeof(App)" render-mode="ServerPrerendered" />
...
@* 當所有組件調用后持久化組件狀態 *@
<persist-component-state />
</body>
FetchData.razor
@page "/fetchdata"
@implements IDisposable
@inject ComponentApplicationState ApplicationState
...
@code {
protected override async Task OnInitializedAsync()
{
ApplicationState.OnPersisting += PersistForecasts;
if (!ApplicationState.TryRedeemPersistedState("fetchdata", out var data))
{
forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
}
else
{
var options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
PropertyNameCaseInsensitive = true,
};
forecasts = JsonSerializer.Deserialize<WeatherForecast[]>(data, options);
}
}
private Task PersistForecasts()
{
ApplicationState.PersistAsJson("fetchdata", forecasts);
return Task.CompletedTask;
}
void IDisposable.Dispose()
{
ApplicationState.OnPersisting -= PersistForecasts;
}
}
注意:這個預覽版中提供了一個
TryRedeemFromJson<T>
輔助方法,但有一個已知的問題,將會在未來的更新中解決。為了解決這個問題,請先使用TryRedeemPersistedState
和手動JSON反序列化,如上例所示。
通過使用與預渲染時相同的狀態來初始化你的組件,任何昂貴的初始化步驟都只需要執行一次。新渲染的 UI 也與預渲染的 UI 相匹配,因此不會發生閃爍。
SignalR - Nullable 注解
ASP.NET Cpre SignalR 客戶端包中已經啟用 Nullability。這意味着,當您 啟用 Nullability時,C# 編譯器將根據您在 SignalR API 中對空值的處理提供適當的反饋。在 .NET 5 中,SignalR 服務器已經更新了 Nullability,但在 .NET 6 中做了一些修改。您可以在 dotnet/aspnetcore #27389 中跟蹤 ASP.NET Core 對 Nullable 注解的支持。
給予反饋
我們希望您喜歡這個 .NET 6 中 ASP.NET Core 的預覽版。我們渴望聽到您對這個版本的體驗。請在 GitHub 上提交問題,讓我們知道你的想法。
感謝你試用 ASP.NET Core!