.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的介紹。javascript

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

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

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

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

開始

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

若是您在Windows上使用Visual Studio進行的話,則還須要安裝Visual Studio 2019的最新預覽web

對於最新的客戶端Blazor模板,還能夠從Visual Studio Marketplace 安裝最新的Blazor擴展算法

升級現有項目

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

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

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

  • 更新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。默認狀況下,客戶端將嘗試當即從新鏈接,並在二、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/

相關文章
相關標籤/搜索