.NET Core 3.0 Preview 6中對ASP.NET Core和Blazor的更新


我們都知道在6月12日的時候微軟發布了.NET Core 3.0的第6個預覽版。針對.NET Core 3.0的發布我們國內的微軟MVP-汪宇傑還發布的官翻版的博文進行了詳細的介紹。具體的可以關注“汪宇傑博客”公眾號,或者我的“DotNetCore實戰”公眾號然后在歷史文章里面進行查閱。而我們這篇文章將會介紹本次更新中對ASP.NET Core和Blazor所做的更新。當然本文的大部分內容翻譯自ASP.NET的首席項目經理Daniel Roth的介紹。

注:英語能力好的可以直接到文章末尾查看英文鏈接進行閱讀。
作者:依樂祝
本文鏈接:https://www.cnblogs.com/yilezhu/p/11031441.html

以下是此預覽版中的新增功能列表:

  • 新Razor特性:@attribute,@code,@key,@namespace,@functions中的標記
  • Blazor指令屬性
  • Blazor應用程序的身份驗證和授權支持
  • Razor類庫中的靜態資產
  • Json.NET不再在項目模板中引用
  • 證書和Kerberos身份驗證
  • SignalR自動重新連接
  • 托管gRPC客戶端
  • gRPC客戶端工廠
  • gRPC攔截器

有關其他詳細信息和已知問題,請參閱發行說明

開始

要在.NET Core 3.0 Preview 6中開始使用ASP.NET Core,請安裝.NET Core 3.0 Preview 6 SDK

如果您在Windows上使用Visual Studio進行的話,則還需要安裝Visual Studio 2019的最新預覽

對於最新的客戶端Blazor模板,還可以從Visual Studio Marketplace 安裝最新的Blazor擴展

升級現有項目

要將現有的ASP.NET Core應用程序升級到.NET Core 3.0 Preview 6,請按照ASP.NET Core文檔中遷移步驟進行操作

另請參閱ASP.NET Core 3.0 中的重大更改的完整列表。

要將現有的ASP.NET Core 3.0 Preview 5項目升級到Preview 6:

  • 更新Microsoft.AspNetCore.*包引用到3.0.0-preview6.19307.2
  • 在Blazor應用程序中:
    • 重命名@functions@code
    • 更新Blazor特定屬性和事件處理程序以使用新的指令屬性語法(參見下文)
    • 刪除任何關於app.UseBlazor<TStartup>()的調用,換成在app.UseRouting()調用之前調用app.UseClientSideBlazorFiles<TStartup>()的方式。還要在app.UseEndpoints()的調用中調用endpoints.MapFallbackToClientSideBlazor<TStartup>("index.html")

之前的調用方式

app.UseRouting();

app.UseEndpoints(endpoints =>
{
    endpoints.MapDefaultControllerRoute();
});

app.UseBlazor<Client.Startup>();

更新之后的調用方式

app.UseClientSideBlazorFiles<Client.Startup>();

app.UseRouting();

app.UseEndpoints(endpoints =>
{
    endpoints.MapDefaultControllerRoute();
    endpoints.MapFallbackToClientSideBlazor<Client.Startup>("index.html");
});

Razor的新特性

我們(因為是ASP.NET的首席項目經理Daniel Roth寫的博客,所以用第一人稱)在此版本中添加了對以下新Razor語言功能的支持。

@attribute

新的@attribute指令將指定的屬性添加到生成的類中。

@attribute [Authorize]

@code

.razor文件(在.cshtml文件中不支持)中使用了新的@code指令來指定要作為附加成員添加到生成的類中的代碼塊。它相當於@functions,但現在有了更好的名稱。

@code {
    int currentCount = 0;

    void IncrementCount()
    {
        currentCount++;
    }
}

@key

.razor文件中使用了新的@key指令屬性,以指定Blazor diffing算法可用於保留列表中的元素或組件的值(任何對象或唯一標識符)。

<div>
    @foreach (var flight in Flights)
    {
        <DetailsCard @key="flight" Flight="@flight" />
    }
</div>

要了解需要此功能的原因,請想象一下不實用此功能來呈現包含航班詳細信息的卡片列表的場景:

<div>
    @foreach (var flight in Flights)
    {
        <DetailsCard Flight="@flight" />
    }
</div>

如果將新航班添加到航班列表的中間,則現有的詳細信息卡實例應保持不受影響,並且應在呈現的輸出中插入一個新的詳細信息卡。

要想象這個,如果Flights以前包含[F0, F1, F2],那么這是之前的狀態:

  • DetailsCard0,Flight = F0
  • DetailsCard1,Flight = F1
  • DetailsCard2,Flight = F2

......如果我們在索引1中插入一個新的項目fnew,這就是所期望的插入之后的狀態:

  • DetailsCard0,Flight = F0
  • DetailsCardNew,Flight = FNew
  • DetailsCard1,Flight = F1
  • DetailsCard2,Flight = F2

但是,實際插入后的狀態如下:

  • DetailsCard0,Flight = F0
  • DetailsCard1,Flight = FNew
  • DetailsCard2,Flight = F1
  • DetailsCardNew,Flight = F2

系統無法知道DetailsCard2或DetailsCard3應保留它們與舊航班實例的關聯,因此它只會將它們與列表中與其位置匹配的航班重新關聯。因此,DetailsCard1和DetailsCard2使用新數據完全重建自己,這是浪費的,有時甚至會導致用戶可見問題(例如,輸入焦點意外丟失)。

通過使用@keydiffing算法添加鍵可以關聯新舊元素或組件。

@namespace

_Imports.razor文件中使用時,指定生成的類或名稱空間前綴的名稱空間。該@namespace指令現在適用於頁面和視圖(.cshtml)應用程序,但現在它也支持組件(.razor)。

@namespace MyNamespace

標記@functions和本地功能

在視圖和頁面(.cshtml文件)中,您現在可以在@functions塊和本地函數中的方法內添加標記。

@{ GreetPerson(person); }

@functions {
    void GreetPerson(Person person)
    {
        <p>Hello, <em>@person.Name!</em></p>
    }
}

Blazor指令屬性

Blazor使用各種屬性來影響組件的編譯方式(例如ref,bind,事件處理程序等)。隨着時間的推移,這些屬性已經有機地添加到Blazor並使用不同的語法。在這個Blazor版本中,我們已經標准化了指令屬性的通用語法。這使得Blazor使用的Razor語法更加一致和可預測。它還為未來的可擴展性鋪平了道路。

指令屬性都遵循以下語法,其中括號中的值是可選的:

@directive(-suffix(:name))(="value")

一些有效的例子:

<!-- directive -->
<div @directive>...</div>
<div @directive="value"></div>

<!-- directive with key/value arg-->
<div @directive:key>...</div>
<div @directive:key="value"></div>

<!-- directive with suffix -->
<div @directive-suffix></div>
<div @directive-suffix="value"></div>

<!-- directive with suffix and key/value arg-->
<div @directive-suffix:key></div>
<div @directive-suffix:key="value"></div>

所有Blazor內置指令屬性都已更新為使用此新語法,如下所述。

事件處理程序

在Blazor中指定事件處理程序現在使用新的指令屬性語法而不是普通的HTML語法。語法類似於HTML語法,但現在具有前導@字符。這使得C#事件處理程序與JS事件處理程序不同。

<button @onclick="@Clicked">Click me!</button>

為C#事件處理程序指定委托時,@屬性值當前仍需要前綴,但我們希望在將來的更新中刪除此要求。

在將來,我們還希望使用指令屬性語法來支持事件處理程序的其他功能。例如,停止事件傳播可能看起來像這樣(尚未實現,但它讓您了解現在由指令屬性啟用的方案):

<button @onclick="Clicked" @onclick:stopPropagation>Click me!</button>

捆綁

<input @bind="myValue">...</input>
<input @bind="myValue" @bind:format="mm/dd">...</input>
<MyButton @bind-Value="myValue">...</MyButton>

<div @key="id">...</div>

參考

<button @ref="myButton">...</button>

Blazor應用程序的身份驗證和授權支持

Blazor現在內置了對處理身份驗證和授權的支持。服務器端Blazor模板現在支持使用ASP.NET Core Identity,Azure AD和Azure AD B2C啟用所有標准身份驗證配置的選項。我們還沒有更新Blazor WebAssembly模板以支持這些選項,但我們計划在.NET Core 3.0發布之后這樣做。

要創建啟用了身份驗證的新Blazor應用程序:

  1. 創建一個新的Blazor(服務器端)項目,然后選擇鏈接以更改身份驗證配置。例如,選擇“個人用戶帳戶”和“在應用程序中存儲用戶帳戶”以將Blazor與ASP.NET Core Identity一起使用:

    Blazor身份驗證

  2. 運行應用程序。該應用程序包含頂行中的鏈接,用於注冊為新用戶並登錄。

    Blazor身份驗證運行

  3. 選擇“注冊”鏈接以注冊新用戶。

    Blazor認證寄存器

  4. 選擇“應用遷移”以將ASP.NET Core Identity遷移應用於數據庫。

    Blazor身份驗證應用遷移

  5. 你現在應該登錄了。

    Blazor身份驗證登錄

  6. 選擇您的用戶名以編輯您的用戶個人資料。

    Blazor身份驗證編輯配置文件

在Blazor應用程序中,Startup使用標准ASP.NET Core中間件在類中配置身份驗證和授權。

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
    endpoints.MapBlazorHub();
    endpoints.MapFallbackToPage("/_Host");
});

使用ASP.NET Core Identity時,所有與身份相關的UI問題都由框架提供的默認身份UI處理。

services.AddDefaultIdentity<IdentityUser>()
    .AddEntityFrameworkStores<ApplicationDbContext>();

應用程序頂行中的身份驗證相關鏈接使用新的內置AuthorizeView組件呈現,該組件根據身份驗證狀態顯示不同的內容。

LoginDisplay.razor

<AuthorizeView>
    <Authorized>
        <a href="Identity/Account/Manage">Hello, @context.User.Identity.Name!</a>
        <a href="Identity/Account/LogOut">Log out</a>
    </Authorized>
    <NotAuthorized>
        <a href="Identity/Account/Register">Register</a>
        <a href="Identity/Account/Login">Log in</a>
    </NotAuthorized>
</AuthorizeView>

AuthorizeView組件僅在授權用戶時顯示其子內容。可替代地,AuthorizeView采用參數用於指定不同模板當用戶是AuthorizedNotAuthorized,或Authorizing。當前的身份驗證狀態通過隱式context參數傳遞給這些模板。您還可以指定AuthorizeView用戶必須滿足的特定角色或授權策略才能查看授權視圖。

要授權訪問Blazor應用程序中的特定頁面,請使用普通的[authorize]屬性。可以使用新的@attribute指令將[authorize]屬性應用於組件。。

@using Microsoft.AspNetCore.Authorization
@attribute [Authorize]
@page "/fetchdata"

要指定在未授權用戶或仍處於授權處理時需要授權的頁面上顯示的內容,請使用組件上的NotAuthorizedContentAuthorizingContent參數Router。這些Router參數僅在此版本的客戶端Blazor中提供支持,但在將來的更新中將為服務器端Blazor啟用它們。

AuthenticationStateProvider無論是在服務器上運行還是在瀏覽器中運行客戶端,新服務都會以統一的方式使Blazor應用程序可以使用身份驗證狀態。在服務器端Blazor應用程序中AuthenticationStateProvider,用戶從HttpContext建立與服務器的連接的表面。客戶端Blazor應用程序可以根據應用程序配置自定義AuthenticationStateProvider。例如,它可以通過查詢服務器上的端點來檢索當前用戶信息。

Task<AuthenticationState>使用該CascadingAuthenticationState組件將身份驗證狀態作為級聯值提供給應用程序。然后,AuthorizeViewRouter組件使用此級聯值來授權對UI的特定部分的訪問。

App.razor

<CascadingAuthenticationState>
    <Router AppAssembly="typeof(Startup).Assembly">
        <NotFoundContent>
            <p>Sorry, there's nothing at this address.</p>
        </NotFoundContent>
    </Router>
</CascadingAuthenticationState>

Razor類庫中的靜態資產

Razor類庫現在可以包含靜態資源,如JavaScript,CSS和圖像。然后,可以通過引用Razor類庫項目或通過包引用將這些靜態資產包含在ASP.NET Core應用程序中。

要在Razor類庫中包含靜態資源,請將一個wwwroot文件夾添加到Razor類庫中,並在該文件夾中包含所有必需的文件。

當具有靜態資產的Razor類庫被引用為項目引用或作為包時,來自庫的靜態資源在路徑前綴_content / {LIBRARY NAME} /下可供應用程序使用。靜態資源保留在其原始文件夾中,Razor類庫中靜態資產內容的任何更改都會反映在應用程序中而不進行重建。

發布應用程序后,所有引用的Razor類庫中的伴隨資源將以相同的前綴復制到已發布應用程序的wwwroot文件夾中。

要嘗試使用Razor類庫中的靜態資源:

  1. 創建默認的ASP.NET Core Web App。

    dotnet new webapp -o WebApp1
    
  2. 創建一個Razor類庫並從Web應用程序引用它。

    dotnet new razorclasslib -o RazorLib1
    dotnet add WebApp1 reference RazorLib1
    
  3. wwwroot文件夾添加到Razor類庫,並包含一個JavaScript文件,該文件將簡單消息記錄到控制台。

    cd RazorLib1
    mkdir wwwroot
    

    hello.js

    console.log("Hello from RazorLib1!");
    
  4. 從Web應用程序中的Index.cshtml引用腳本文件。

    <script src="_content/RazorLib1/hello.js"></script>
    
  5. 運行應用程序並在瀏覽器控制台中查找輸出。

    Hello from RazorLib1!
    

項目現在默認使用System.Text.Json

現在,新的ASP.NET Core項目將默認使用System.Text.Json進行JSON處理。在此版本中,我們從項目模板中刪除了Json.NET(Newtonsoft.Json)。要啟用對使用Json.NET的支持,請將Microsoft.AspNetCore.Mvc.NewtonsoftJson包添加到項目中,並AddNewtonsoftJson()Startup.ConfigureServices方法中添加對以下代碼的調用。例如:

services.AddMvc()
    .AddNewtonsoftJson();

證書和Kerberos身份驗證

預覽6為ASP.NET Core帶來了證書和Kerberos身份驗證。

證書身份驗證要求您將服務器配置為接受證書,然后在Startup.Configure中添加身份驗證中間件和在Startup.ConfigureServices中配置證書身份驗證服務。

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication(
        CertificateAuthenticationDefaults.AuthenticationScheme)
            .AddCertificate();
    // All the other service configuration.
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseAuthentication();
    // All the other app configuration.
}

證書身份驗證選項包括接受自簽名證書,檢查證書吊銷以及檢查提供的證書中是否包含正確的使用標記的功能。默認用戶主體是從證書屬性構造的,其中包含一個允許您補充或替換主體的事件。有關如何為證書身份驗證配置公共主機的所有選項和說明,請參閱文檔

我們還將“Windows身份驗證”擴展到Linux和macOS上。以前,此身份驗證類型僅限於IIS和HttpSys,但現在Kestrel可以使用Microsoft.AspNetCore.Authentication.Negotiate nuget包在Windows,Linux和macOS上為Windows域加入的主機使用Negotiate,Kerberos和NTLM。與配置身份驗證應用程序范圍的其他身份驗證服務一樣,然后配置服務:

public void ConfigureServices(IServiceCollection services)
{ 
    services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
        .AddNegotiate();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseAuthentication();
    // All the other app configuration.
}

必須正確配置主機。Windows主機必須將SPN添加到托管應用程序的用戶帳戶。必須將Linux和macOS計算機加入域,然后必須為Web進程創建SPN,以及在主機上生成和配置的keytab文件。文檔中給出了完整的說明。

SignalR自動重新連接

此預覽版本現已通過npm install @aspnet/signalr@next 和.NET Core SignalR Client方式進行提供,包括一個新的自動重新連接功能。在這個版本中,我們已經將withAutomaticReconnect()方法添加到了HubConnectionBuilder。默認情況下,客戶端將嘗試立即重新連接,並在2、10和30秒后重新連接。參與自動重新連接是可選的,但通過這種新方法很簡單。

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/chatHub")
    .withAutomaticReconnect()
    .build();

通過將一系列基於毫秒的持續時間傳遞給該方法,您可以非常精細地了解重新連接嘗試如何隨時間發生。

.withAutomaticReconnect([0, 3000, 5000, 10000, 15000, 30000])
//.withAutomaticReconnect([0, 2000, 10000, 30000]) yields the default behavior

或者,您可以傳遞自定義重新連接策略的實現,該策略可以讓您完全控制。

如果30秒后重新連接失敗(或您設置的最大值),客戶端會假定連接處於脫機狀態,並停止嘗試重新連接。在這些重新連接嘗試期間,您將希望更新應用程序UI,以向用戶提供嘗試重新連接的提示。

重新連接事件處理程序

為了簡化這一過程,我們將SignalR客戶端API擴展為包含onreconnectingonreconnected事件處理程序。第一個處理程序onreconnecting為開發人員提供了一個禁用UI或讓用戶知道應用程序處於脫機狀態的好機會。

connection.onreconnecting((error) => {
    const status = `Connection lost due to error "${error}". Reconnecting.`;
    document.getElementById("messageInput").disabled = true;
    document.getElementById("sendButton").disabled = true;
    document.getElementById("connectionStatus").innerText = status;
});

同樣,onreconnected處理程序使開發人員有機會在重新建立連接后更新UI。

connection.onreconnected((connectionId) => {
    const status = `Connection reestablished. Connected.`;
    document.getElementById("messageInput").disabled = false;
    document.getElementById("sendButton").disabled = false;
    document.getElementById("connectionStatus").innerText = status;
});

了解有關自定義和處理重新連接的詳細信息

預覽版本中已經部分記錄了自動重新連接。請訪問https://aka.ms/signalr/auto-reconnect,查看有關該主題的更深入的文檔,以及有關使用的更多示例和詳細信息。

托管gRPC客戶端

在之前的預覽中,我們依靠Grpc.Core庫來獲取客戶端支持。HttpClient在此預覽中添加HTTP / 2支持使我們能夠引入完全托管的gRPC客戶端。

要開始使用新客戶端,請添加包引用Grpc.Net.Client,然后您可以創建新客戶端。

var httpClient = new HttpClient() { BaseAddress = new Uri("https://localhost:5001") };
var client = GrpcClient.Create<GreeterClient>(httpClient);

gRPC客戶端工廠

基於我們介紹的固定模式HttpClientFactory,我們添加了一個gRPC客戶端工廠,用於在項目中創建gRPC客戶端實例。我們添加了兩種工廠:Grpc.Net.ClientFactoryGrpc.AspNetCore.Server.ClientFactory

Grpc.Net.ClientFactory設計用於non-ASP.NET應用模型的使用(如工人服務)仍然使用Microsoft.Extensions.*原語不會對ASP.NET核心的依賴。

Grpc.Net.ClientFactory設計用於仍使用Microsoft.Extensions.*基元(不依賴於ASP.NET核心)的非ASP.NET應用程序模型(如Worker Services)。

在執行服務到服務通信的應用程序中,我們經常發現大多數服務器也是使用其他服務的客戶端。在這些情況下,我們建議使用Grpc.AspNetCore.Server.ClientFactory它具有自動傳播gRPC截止日期和取消令牌的功能。

要使用客戶端工廠,請在將以下代碼添加到configureServices()之前,將適當的包引用添加到項目(Grpc.AspNetCore.Server.FactoryGrpc.Net.ClientFactory)。

services
    .AddGrpcClient<GreeterClient>(options =>
    {
        options.BaseAddress = new Uri("https://localhost:5001");
    });

gRPC攔截器

gRPC公開了一種機制來攔截客戶端和服務器上的RPC調用。攔截器可以與現有的HTTP中間件結合使用。與HTTP中間件不同,攔截器允許您在序列化之前(在客戶端上)和反序列化之后(在服務器上)訪問實際的請求/響應對象,反之亦然。所有中間件都在請求端的攔截器之前運行,反之亦然。

客戶端攔截器

與客戶端工廠一起使用時,可以添加客戶端攔截器,如下所示。

services
    .AddGrpcClient<GreeterClient>(options =>
    {
        options.BaseAddress = new Uri("https://localhost:5001");
    })
    .AddInterceptor<CallbackInterceptor>();

服務器攔截器

服務器攔截器可以ConfigureServices()如下所示進行注冊。

services
    .AddGrpc(options =>
    {
        // This registers a global interceptor
        options.Interceptors.Add<MaxStreamingRequestTimeoutInterceptor>(TimeSpan.FromSeconds(30));
    })
    .AddServiceOptions<GreeterService>(options =>
    {
        // This registers an interceptor for the Greeter service
        options.Interceptors.Add<UnaryCachingInterceptor>();
    });

有關如何編寫攔截器的示例,請查看grpc-dotnet repo中的這些示例

給予反饋

我們希望您喜歡ASP.NET Core和Blazor預覽版中的新功能!請通過在GitHub上提交問題告訴我們您的想法。(再次聲明,本文大多內容翻譯自:ASP.NET首席項目經理Daniel Roth的介紹,因此才會有這段話。)

感謝您試用ASP.NET Core和Blazor!

原文地址:https://devblogs.microsoft.com/aspnet/asp-net-core-and-blazor-updates-in-net-core-3-0-preview-6/


免責聲明!

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



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