天天看點

.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,這就是所期望的插入之後的狀态:

  • DetailsCardNew,Flight = FNew

但是,實際插入後的狀态如下:

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

系統無法知道DetailsCard2或DetailsCard3應保留它們與舊航班執行個體的關聯,是以它隻會将它們與清單中與其位置比對的航班重新關聯。是以,DetailsCard1和DetailsCard2使用新資料完全重建自己,這是浪費的,有時甚至會導緻使用者可見問題(例如,輸入焦點意外丢失)。

通過使用

@key

diffing算法添加鍵可以關聯新舊元素或元件。

@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使用各種屬性來影響元件的編譯方式(例如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模闆現在支援使用ASP.NET Core Identity,Azure AD和Azure AD B2C啟用所有标準身份驗證配置的選項。我們還沒有更新Blazor WebAssembly模闆以支援這些選項,但我們計劃在.NET Core 3.0釋出之後這樣做。

要建立啟用了身份驗證的新Blazor應用程式:

  1. 建立一個新的Blazor(伺服器端)項目,然後選擇連結以更改身份驗證配置。例如,選擇“個人使用者帳戶”和“在應用程式中存儲使用者帳戶”以将Blazor與ASP.NET Core Identity一起使用:
    .NET Core 3.0 Preview 6中對ASP.NET Core和Blazor的更新
  2. 運作應用程式。該應用程式包含頂行中的連結,用于注冊為新使用者并登入。
    .NET Core 3.0 Preview 6中對ASP.NET Core和Blazor的更新
  3. 選擇“注冊”連結以注冊新使用者。
    .NET Core 3.0 Preview 6中對ASP.NET Core和Blazor的更新
  4. 選擇“應用遷移”以将ASP.NET Core Identity遷移應用于資料庫。
    .NET Core 3.0 Preview 6中對ASP.NET Core和Blazor的更新
  5. 你現在應該登入了。
    .NET Core 3.0 Preview 6中對ASP.NET Core和Blazor的更新
  6. 選擇您的使用者名以編輯您的使用者個人資料。
    .NET Core 3.0 Preview 6中對ASP.NET Core和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

采用參數用于指定不同模闆當使用者是

Authorized

NotAuthorized

,或

Authorizing

。目前的身份驗證狀态通過隐式

context

參數傳遞給這些模闆。您還可以指定

AuthorizeView

使用者必須滿足的特定角色或授權政策才能檢視授權視圖。

要授權通路Blazor應用程式中的特定頁面,請使用普通的

[authorize]

屬性。可以使用新的

@attribute

指令将

[authorize]

屬性應用于元件。。

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

要指定在未授權使用者或仍處于授權處理時需要授權的頁面上顯示的内容,請使用元件上的

NotAuthorizedContent

AuthorizingContent

參數

Router

。這些

Router

參數僅在此版本的用戶端Blazor中提供支援,但在将來的更新中将為伺服器端Blazor啟用它們。

AuthenticationStateProvider

無論是在伺服器上運作還是在浏覽器中運作用戶端,新服務都會以統一的方式使Blazor應用程式可以使用身份驗證狀态。在伺服器端Blazor應用程式中

AuthenticationStateProvider

,使用者從

HttpContext

建立與伺服器的連接配接的表面。用戶端Blazor應用程式可以根據應用程式配置自定義

AuthenticationStateProvider

。例如,它可以通過查詢伺服器上的端點來檢索目前使用者資訊。

Task<AuthenticationState>

使用該

CascadingAuthenticationState

元件将身份驗證狀态作為級聯值提供給應用程式。然後,

AuthorizeView

Router

元件使用此級聯值來授權對UI的特定部分的通路。

App.razor

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

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();
           

預覽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檔案。文檔中給出了完整的說明。

此預覽版本現已認證

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擴充為包含

onreconnecting

onreconnected

事件處理程式。第一個處理程式

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.Core

庫來擷取用戶端支援。

HttpClient

在此預覽中添加HTTP / 2支援使我們能夠引入完全托管的gRPC用戶端。

要開始使用新用戶端,請添加包引用

Grpc.Net.Client

,然後您可以建立新用戶端。

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

基于我們介紹的固定模式

HttpClientFactory

,我們添加了一個gRPC用戶端工廠,用于在項目中建立gRPC用戶端執行個體。我們添加了兩種工廠:

Grpc.Net.ClientFactory

Grpc.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.Factory

Grpc.Net.ClientFactory

)。

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

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/

作者:依樂祝(祝雷)

出處:https://www.cnblogs.com/yilezhu

聯系:[email protected] .NET Core實戰項目交流群:637326624 微信:jkingzhu

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。如有問題或建議,請多多賜教,非常感謝。

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

繼續閱讀