ASP.NET Core 在 .NET 6 Preview 2 中的更新


原文:《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 模板時的構建時間改進。

Razor 構建的性能改進

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" />

然后,這些樣式將只應用於各自的視圖和頁面。

MVC CSS isolation

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)允許泛型類型推斷出,對於有同名類型參數的子代,可以自動使用指定的類型參數。

例如,你可以定義像這樣的 GridColumn 組件:

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; }
}

然后你可以像這樣使用 GridColumn 組件:

<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!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM