歡迎光臨
每天分享高質量文章

.NET Core 3.0 Preview 3中關於ASP.NET Core的更新內容

.NET Core 3.0 Preview 3已經推出,它包含了一系列關於ASP.NET Core的新的更新。

下麵是該預覽版的更新串列:

  • Razor元件改進:
    • 單專案模板 
    • 新的Razer擴充套件
    • Endpoint路由整合
    • 預呈現
    • Razor類庫中的Razor元件
    • 改進事件處理 
    • Forms & validation
  • 執行時編譯
  • Worker服務模板
  • gRPC模板
  • Angular模板已更新為Angular 7
  • SPA認證 
  • SignalR與Endpoint路由整合
  • SignalR Java客戶端支援長輪詢

其他詳細資訊和已知問題,請參閱發行說明。

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

如果您使用的是Visual Studio,則還需要安裝Visual Studio 2019的最新預覽版【譯者註:目前VS2019正式版已經釋出,直接安裝正式版即可】。

  • 註意:要在Visual Studio 2019中使用.NET Core 3.0預覽版,需要啟用選項以使用.NET Core SDK預覽版,方法是透過【工具>選項>專案和解決方案> .NET Core>使用.NET Core SDK預覽版

將現有的ASP.NET Core應用程式升級到.NET Core 3.0 Preview 3,請按照ASP.NET Core檔案中的遷移步驟進行操作。

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

在前面的預覽中,我們介紹了Razor元件,這是一種用ASP.NET核心構建互動式客戶端Web UI的新方法。本節將會介紹我們在該預覽更新中對Razor元件所做的各種改進。

單專案模板

Razor元件專案模板現在是單個專案,而不是同一解決方案中的兩個專案。所編寫的Razor元件位於託管它們的ASP.NET Core應用程式中。同一個ASP.NET Core專案可以包含Razor元件、頁面和檢視。Razor元件模板與其他ASP.NET Core Web應用程式模板一樣,預設情況下也啟用了HTTPS。

新的Razer擴充套件

Razor元件使用Razor語法編寫,但編譯方式與Razor頁面和檢視不同。為了明確哪些Razor檔案應該編譯為Razor元件,我們引入了一個新的檔案副檔名:.razor。在Razor元件模板中,所有元件檔案現在都使用.razor副檔名。Razor頁面和檢視仍然使用.cshtml副檔名。

只要使用_RazorComponentInclude MSBuild屬性將這些檔案標識為Razor元件檔案,Razor元件仍然可以使用.cshtml檔案副檔名來建立。例如,該版本中的Razor元件模板指定Components檔案夾下的所有.cshtml檔案為Razor元件。

   1:  <_razorcomponentinclude>Components\**\*.cshtml</_razorcomponentinclude>

請註意,這個版本中的.razor檔案有很多限制。有關已知問題和可用解決方案的串列,請參考釋出說明。

Endpoint路由整合

Razor元件現在已經整合到了ASP.NET Core中新的Endpoint路由系統。要在應用程式中啟用Razor元件支援,需要在路由配置中使用MapComponentHub。

   1:  app.UseRouting(routes =>
   2:  {
   3:      routes.MapRazorPages();
   4:      routes.MapComponentHub("app");

這會將應用程式配置以接受互動式Razor元件的傳入連線,並指定根元件App應該在匹配選擇器App的DOM元素中呈現。

預呈現

預設情況下,Razor元件專案模板執行服務端預渲染。也就是說當使用者瀏覽您的應用程式時,伺服器將對您的Razor元件執行初始化渲染,並將結果作為純靜態HTML傳遞給瀏覽器。然後,瀏覽器將透過SignalR重新連線到伺服器,並將Razor元件切換為完全互動的樣式。這兩個階段的交付是有益的,因為:

  • 它提高了站點的感知能力,因為使用者介面可以更快地出現,而無需等待進行任何WebSocket連線,甚至執行任何客戶端指令碼。這對連線速度較慢的使用者有著更大的影響,如2G/3G手機。
  • 它可以讓搜尋引擎很容易的搜尋到你的應用程式。

對於使用更快連線的使用者(如內網使用者),此功能的影響較小,因為無論如何使用者介面都應該立即出現。

設定預渲染,Razor元件專案模板不會有靜態HTML檔案。取而代之的是單個Razor頁面/Pages/Index.cshtml,使用Html.RenderComponentAsync() HTML幫助器預呈現應用程式內容。該頁面還取用components.server.js指令碼,在預呈現和下載內容後設定SignalR 連線。由於這是一個Razor頁面,像環境標簽助手這樣的功能就可以工作了。

Index.cshtml

   1:  @page "{*clientPath}"
   2:  DOCTYPE html>
   3:  <html>
   4:  <head>
   5:      ...
   6:  head>
   7:  <body>
   8:      <app>@(await Html.RenderComponentAsync<App>())app>
   9:  
  10:      <script src="_framework/components.server.js">script>
  11:  body>
  12:  html>

除了應用程式載入速度更快之外,還可以在瀏覽器開發工具中檢視下載的HTML原始碼,從而可以看到預渲染正在進行。Razor元件在HTML中是完全呈現的。

Razor類庫中的Razor元件

現在可以將Razor元件新增到Razor類庫中,並使用Razor元件從ASP.NET核心專案取用它們。

在Razer類庫中建立可重用的Razer元件:

1、建立Razer元件應用程式

   1:  dotnet new razorcomponents -o RazorComponentsApp1

2、建立Razer類庫

   1:  dotnet new razorclasslib -o RazorClassLib1

3、新增Component1.razor檔案到Razer類庫

Component1.razor

   1:  

Component1


   2:  
   3:  

@message


   4:  
   5:  @functions {
   6:      string message = "Hello from a Razor Class Library"!;
   7:  }

1、使用Razor元件從ASP.NET Core應用程式取用Razor類庫

   1:  dotnet add RazorComponentsApp1 reference RazorClassLib1

在Razor元件應用程式中,使用@addTagHelper指令從Razor類庫匯入所有元件,然後在應用程式中使用component1

Index.razor

   1:  @page "/"
   2:  @addTagHelper *, RazorClassLib1
   3:  
   4:  

Hello, world!


   5:  
   6:  Welcome to your new app.
   7:  
   8:  

註意:在此版本中,Razer類庫與Blazor應用程式並不相容。另外,Razor類庫還不支援靜態資源。如果要在庫中建立可與Blazor和Razor元件應用程式共享的元件,仍然需要使用Blazor類庫。這寫問題會在未來的更新中解決。

改進事件處理

新的eventcallback和eventcallback<>型別使得定義元件回呼更加簡單。例如,考慮以下兩個元件:

MyButton.razor

   1:  

>Click here and see what happens!

   2:  
   3:  @functions {
   4:      [Parameter] EventCallback OnClick { get; set; }
   5:  }

UsesMyButton.razor

   1:  
@text

   2:  
   3:  "ShowMessage"

/>

   4:  
   5:  @function {
   6:      string text;
   7:  
   8:      void ShowMessage(UIMouseEventArgs e)
   9:      {
  10:          text = "Hello, world!";
  11:      }
  12:  }

onclick回呼的型別是EventCallback(取代Action),MyButton直接傳遞給onclick事件處理程式。編譯器處理將委託轉換為EventCallback的過程,並將執行其他一些操作,以確保呈現過程具有足夠的資訊來呈現正確的標的元件。因此,不需要在ShowMessage事件處理程式中顯式呼叫StateHasChanged。編譯器處理將委託轉換為EventCallback的過程,並將執行其他一些操作,以確保渲染過程具有足夠的資訊來渲染正確的標的元件。因此,不需要在ShowMessage事件處理程式中顯式呼叫StateHasChanged。

透過使用EventCallback<>型別的OnClick處理程式可以是非同步的,而不需要對MyButton進行任何其他程式碼的修改。

UsesMyButton.razor

   1:  
@text

   2:  
   3:  "ShowMessageAsync"

/>

   4:  
   5:  @function {
   6:      string text;
   7:  
   8:      async Task ShowMessageAsync(UIMouseEventArgs e)
   9:      {
  10:          await Task.Yield();
  11:          text = "Hello, world!";
  12:      }
  13:  }

我們建議在為事件處理和系結定義元件引數時使用EventCallback and EventCallback。盡可能使用EventCallback<>,因為它是強型別的並且可以向元件的使用者提供更好的反饋。當沒有傳遞給回呼函式的值時,也使用EventCallback。

Forms&validation;

此預覽版本添加了用於處理表單和驗證的內建元件和基礎結構。

使用. net進行客戶端web開發的一個好處是能夠在客戶端和伺服器之間共享相同的實現邏輯。驗證邏輯是一個很好的邏輯。Razor元件中的新的Forms&validation;支援包括使用資料註解處理驗證的支援,或者可以插入你喜歡的驗證系統。

例如,以下Person型別使用資料註解定義驗證邏輯:

   1:  public class Person
   2:  {
   3:      [Required(ErrorMessage = "Enter a name")]
   4:      [StringLength(10, ErrorMessage = "That name is too long")]
   5:      public string Name { get; set; }
   6:  
   7:      [Range(0, 200, ErrorMessage = "Nobody is that old")]
   8:      public int AgeInYears { get; set; }
   9:  
  10:      [Required]
  11:      [Range(typeof(bool), "true", "true", ErrorMessage = "Must accept terms")]
  12:      public bool AcceptsTerms { get; set; }
  13:  }

以下是如何基於Person模型鎖建立的驗證表單:

   1:  "@person"

OnValidSubmit=“@HandleValidSubmit”>

   2:  
   3:  
   4:  
   5:  

class


=“name”>

   6:          Name: "@person.Name" />
   7:  
   8:  

class


=“age”>

   9:          Age (years): "@person.AgeInYears" />
  10:  
  11:  

class


=“accepts-terms”>

  12:          Accepts terms: "@person.AcceptsTerms" />
  13:  
  14:  
  15:      

>Submit

  16:  
  17:  
  18:  @functions {
  19:      Person person = new Person();
  20:  
  21:      void HandleValidSubmit()
  22:      {
  23:          Console.WriteLine("OnValidSubmit");
  24:      }
  25:  }

如果將此表單新增到應用程式中,並執行它,你將獲得一個基本表單,該表單在欄位更改和表單提交時自動進行欄位輸入值的驗證。

這裡發生了很多事情,讓我們把它一個一個地分解:

  • 這個表單是使用新的EditForm元件定義的。EditForm將EditContext設定為一個級聯相關的值,該值用於跟蹤關於編輯過程的元資料(例如,已修改的內容、當前驗證訊息等)。EditForm還為有效和無效提交(OnValidSubmit、OnInvalidSubmit)提供了合適的事件。如果想自己觸發驗證,也可以直接使用OnSubmit。
  • DataAnnotationsValidator元件使用資料註解,以驗證支援附加到級聯的EditContext。 使用資料註釋啟用驗證支援需要顯式呼叫,但我們正在考慮將其作為預設行為,但隨後你可以改寫它。
  • 每個表單欄位都是使用一組內建的輸入元件(InputText, InputNumber, InputCheckbox, InputSelect等)定義的。這些元件提供預設行為,用於在編輯時驗證並更改它們的CSS類以反映欄位狀態。其中一些具有有用的分析邏輯(例如,InputDate和InputNumber將不可解析的值註冊為驗證錯誤,這樣可以優雅地處理它們)。相關欄位還支援標的欄位的可空性(例如,int?)。
  • ValidationMessage元件顯示特定欄位的驗證訊息。
  • ValidationSummary元件彙總所有驗證訊息(類似於驗證摘要標記助手)。

內建的輸入元件存在一些限制,我們希望在將來的更新中改進這些限制。例如,目前不能在生成輸入標記上指定任意屬性。將來,我們計劃啟用元件的所有額外屬性。現在,您需要構建自己的元件子類來處理這些情況。

執行時驗證

對執行時編譯的支援已從.NET Core 3.0中的ASP.NET核心共享框架中刪除,但現在可以透過嚮應用程式新增包的方式來啟用它。

啟用執行時編譯:

新增Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation

   1:  "Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation"

Version=“3.0.0-preview3-19153-02” />

在Startup.ConfigureServices新增對AddRazorRuntimeCompilation的呼叫

   1:  services.AddMvc().AddRazorRuntimeCompilation();

Worker服務模板

在preview3中,我們引入了一個名為“Worker Service”的新模板。此模板被設計為執行長時間執行的後臺行程的起點,就像您可能作為Windows服務或Linux守護行程執行一樣。例如,從訊息佇列生成/消費訊息,或者監視要處理的檔案。它旨在支援ASP.NET Core的生產力功能,如日誌記錄,DI,配置等,而不承載任何Web依賴項。

在接下來的幾天裡,我們將釋出一些部落格文章,提供更多關於使用Worker模板入門的練習。我們將有一些專門官微Windows/SystemD服務釋出、在ACI/AKS上執行以及作為WebJob執行的文章。

提醒

雖然其目的是使工作模板預設情況下不依賴於web技術,但在preview3中它仍然使用web SDK,併在您選擇“ASP.NET Core WebApplication”之後顯示出來。

Angular模板更新到了Angular 7

Angular模板更新到了Angular 7。在 .NET Core 3.0 釋出穩定版本之前,我們預計會更新到Angular 8。

SPA身份認證

這個版本,在Angular和React模板中引入了對身份驗證的支援。在本節中,我們將展示如何建立一個新的Angular或React模板,該模板允許我們對使用者進行身份驗證並訪問受保護的API資源。

我們對使用者身份驗證和授權的支援是由IdentityServer在後臺提供的,我們構建了一些擴充套件來簡化我們特定場景的配置體驗。

註意:在本文中,我們展示了對Angular的身份驗證支援,但在React模板中提供了相同的功能。

建立新的Angular應用程式

要建立一一個新的支援身份驗證的Angular應用程式,我們需要呼叫以下命令:

   1:  dotnet new angular -au Individual

這個命令建立一個新的ASP.NET Core應用程式和託管的客戶端Angular應用程式。ASP.NET Core應用程式包括已配置的Identity Server實體,可是讓Angular應用程式很方面的對使用者進行身份驗證,並針對ASP.NET Core應用程式中的受保護資源傳送HTTP請求。

Angular模組所構建的身份驗證和授權支援,可以匯入到您的應用程式中,並提供一套元件和服務來增強主應用程式模組的功能。

執行該應用程式

要執行應用程式,只需執行以下命令,然後用瀏覽器開啟控制臺上顯示的URL:

   1:  dotnet run
   1:  Hosting environment: Development
   2:  Content root path: C:\angularapp
   3:  Now listening on: https://localhost:5001
   4:  Now listening on: http://localhost:5000
   5:  Application started. Press Ctrl+C to shut down.

執行結果如下:

當我們開啟應用程式時,我們會看到常用的Home、Counter和Fetch資料選單選項以及兩個新選項:Register和Login。如果單擊Register,我們將被髮送到預設的認證介面(在執行遷移和更新資料庫之後),在那裡我們可以註冊為新使用者。

註冊為新使用者後,我們將被重定向回應用程式,在那裡我們可以看到我們成功地透過了身份驗證。

呼叫經過身份驗證的API

如果我們點選獲取資料,我們可以看到天氣預報資料串列

保護現有的API

要保護伺服器上的API,只需要在要保護的控制器或操作上使用[Authorize]屬性。

   1:  [Authorize]
   2:  [Route("api/[controller]")]
   3:  public class SampleDataController : Controller
   4:  {
   5:  ...
   6:  }

客戶端路徑認證

為了在Angular應用程式訪問頁面時,要求對使用者進行身份驗證,我們將[AuthorizeGuard]應用到正在配置的路由上。

   1:  import { ApiAuthorizationModule } from 'src/api-authorization/api-authorization.module';
   2:  import { AuthorizeGuard } from 'src/api-authorization/authorize.guard';
   3:  import { AuthorizeInterceptor } from 'src/api-authorization/authorize.interceptor';
   4:  
   5:  @NgModule({
   6:    declarations: [
   7:      AppComponent,
   8:      NavMenuComponent,
   9:      HomeComponent,
  10:      CounterComponent,
  11:      FetchDataComponent
  12:    ],
  13:    imports: [
  14:      BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }),
  15:      HttpClientModule,
  16:      FormsModule,
  17:      ApiAuthorizationModule,
  18:      RouterModule.forRoot([
  19:        { path: '', component: HomeComponent, pathMatch: 'full' },
  20:        { path: 'counter', component: CounterComponent },
  21:        { path: 'fetch-data', component: FetchDataComponent, canActivate: [AuthorizeGuard] },
  22:      ])
  23:    ],
  24:    providers: [
  25:      { provide: HTTP_INTERCEPTORS, useClass: AuthorizeInterceptor, multi: true }
  26:    ],
  27:    bootstrap: [AppComponent]
  28:  })
  29:  export class AppModule { }

帶有SignalR Hubs的Endpoint路由

在preview3中,我們將SignalR hubs連線到最近釋出的新端點路由特性中。SignalR hub連線之前已經明確完成:

   1:  app.UseSignalR(routes =>
   2:  {
   3:      routes.MapHub("hubs/chat");
   4:  });

這意味著開發人員需要在啟動期間將控制器、Razor頁面和hubs連線到不同的位置,從而產生一系列幾乎相同的路由片段:

   1:  app.UseSignalR(routes =>
   2:  {
   3:      routes.MapHub("hubs/chat");
   4:  });
   5:  
   6:  app.UseRouting(routes =>
   7:  {
   8:      routes.MapRazorPages();
   9:  });

現在,SignalR hub也可以透過endpoint路由進行路由分發,因此您可以在ASP.NET Core中一站式地路由幾乎所有內容。

   1:  app.UseRouting(routes =>
   2:  {
   3:      routes.MapRazorPages();
   4:      routes.MapHub("hubs/chat");
   5:  });

Java SignalR客戶端的長輪詢

我們向Java客戶端添加了長輪詢支援,這使它能夠在不支援WebSockets的環境中建立連線。這也使您能夠在客戶端應用程式中專門選擇長輪詢傳輸。

gRPC 模板

這個預覽版引入了一個用ASP.NET Core構建的gRPC服務的新模板。NET Core使用一個新的gRPC框架,我們正在與谷歌合作構建。

gRPC是一個流行的RPC(遠端過程呼叫)框架,它為API開發提供了一種固定的契約優先方法。它使用HTTP/2進行傳輸,協議緩衝區作為介面描述語言,並提供諸如身份驗證、雙向流和流控制、取消和超時等功能。

這些模板建立了兩個專案:一個是託管於ASP. NET Core中的gRPC服務,以及一個用於測試它的控制檯應用程式。

這是第一個為ASP.NET Core公開釋出的gRPC預覽,並沒有實現gRPC的所有功能,但是我們正在努力使ASP.NET Core提供所提供得最佳的gRPC體驗成為可能。請嘗試一下,併在GitHub上的grpc/grpc-dotnet上給我們反饋。

未來將會有更詳細地討論ASP.NET Core使用gRPC的部落格文章,請繼續關註。

反饋

我們希望您喜歡這個預覽版的ASP.NET Core中的新功能!請透過在Github上提交問題讓我們知道你的想法。

已同步到看一看
贊(0)

分享創造快樂