2017 年 11 月

第 33 卷,第 11 期

本文章是由機器翻譯。

技術最前線 - ASP.NET MVC Core 檢視的方針

Dino Esposito | 2017 年 11 月

Dino Esposito雖然 ASP.NET Core 看起來非常類似於傳統的 ASP.NET MVC 介面上,有許多背後原理的差異。控制站、 Razor 檢視,即使模型類別通常可輕鬆地移轉最少的工作,但在架構上而言,ASP.NET Core 偏離大幅先前的非核心版本的 ASP.NET。

主要的原因是重寫的管線中,提供 ASP.NET Core 應用程式至少兩種方式產生 HTML 為基礎的回應。如預期般,應用程式可以採用 MVC 程式撰寫模型,並從控制器動作透過叫用的 Razor 檢視產生 HTML。或者,應用程式可以做為非常細的 Web 伺服器,根據某些終止中介軟體建立,而該終止的中介軟體中的程式碼可以執行所有項目,包括傳回瀏覽器會視為 HTML 字串。最後,在 ASP.NET Core 2.0 您可以使用全新的方式-Razor 頁面。Razor 頁面都不需要 MVC 基礎結構,但能產生和處理 HTML 直接從 Razor 檔案的 Razor 檢視。

在本文中迷你伺服器、 終止的中介軟體和 Razor 頁面上的快速討論之後我對比,比較您要建立檢視的 MVC 程式設計模型中有的方法。特別是,我將焦點放在新 ASP.NET Core,包括標記協助程式、 檢視元件和相依性插入 (DI) 和實際的編碼方式及其影響功能。

終止的中介軟體的 HTML

終止的中介軟體為取得處理要求的 ASP.NET Core 管線中的程式碼的最後一個區塊。基本上,它是您用來處理 HTTP 要求是否產生任何類型的偵測回應,函式 (lambda) 直接純文字、 JSON、 XML、 二進位或 HTML。以下是範例啟動類別針對此目的:

public class Startup
{
  public void Configure(IApplicationBuilder app)
  {
    app.Run(async context =>
    {
    var html = BuildHtmlFromRequest(context);
    await context.Response.WriteAsync(html);
    });
  }
}

HTML 格式的文字寫入回應的輸出資料流,並設定適當的 MIME 類型,您都可以做 HTML 內容加入至瀏覽器。是很直接的方式,與沒有篩選器和任何 intermediation,但明確地運作,而且速度比在舊版 ASP.NET 中的任何項目。終止中介軟體可讓您控制對流量比其他任何選項更快。很明顯地,撰寫程式碼結束的中介軟體中將 HTML factory 往右遠低於正在維護且彈性的方案,但它的運作方式。

Razor 頁面

在 ASP.NET Core 2.0 中,Razor 頁面會提供以其他方式提供 HTML 內容,來直接叫用 Razor 的範本檔案,而不需透過控制器和動作。只要 Razor 頁面檔案位於 [Pages] 資料夾和其相對路徑和名稱符合所要求的 URL,檢視引擎將會處理內容,並產生 HTML。

真的差異 Razor 網頁及 Razor 檢視是 Razor 頁面可以是單一檔案 — 十分類似 ASPX 頁面,其中包含程式碼和標記。Razor 頁面是可為系統提供的 PageModel 類別會繼承的檢視模型繫結的 @page 指示詞已標幟的 CSHTML 檔案。如已所述,所有 Razor 頁面都到新的頁面根專案資料夾下,路由會遵循簡單的模式。在 [Pages] 資料夾中的 URL 已進行 root 破解,.cshtml 延伸去除實際的檔案名稱。如需有關 Razor 頁面的詳細資訊,看看bit.ly/2wpOdUE。此外,如需更進階的範例,看看msdn.com/magazine/mt842512

如果您習慣使用 MVC 控制器,應該會有本質上是無意義,可能只是使用最低限度很有幫助在這些極少數的情況下,您需要控制器方法呈現出不提供任何商務邏輯檢視的位置中,您會發現 Razor 頁面。相反地,如果您還不熟悉 MVC 應用程式模型,Razor 頁面會提供用於主控 ASP.NET Core framework 的另一個選項。為了某些人來說 Razor 頁面會提供較低的屏障的項目進度的架構。

標記協助程式

Razor 語法一直基本上與 C# 程式碼的程式碼片段顛倒 HTML 範本。@ 符號可用來告知 Razor 剖析器發生 HTML 靜態內容和程式碼片段之間轉換。任何文字後面 @ 符號會剖析根據 C# 語言的語法規則。文字在剖析期間探索到的項目會串連來編譯使用.NET 編譯器平台 ("Roslyn") 的即時的表單以動態建立的 C# 類別。執行 C# 類別就會累積混合在一起靜態內容和動態計算的內容回應資料流中的 HTML 文字。最後,Razor 語言的表達限於 HTML5 的表現。

Razor、 ASP.NET 團隊也引進所謂的 HTML helper 的成品。HTML helper 是一種小型 HTML 工廠,取得一些輸入的資料,並發出您想要的 HTML。不過,HTML helper 永遠不會贏了透過開發人員,以便在 ASP.NET Core 已經新增多更好的工具: 標記協助程式。標記協助程式播放相同角色做為 HTML helper — 可做為 HTML 處理站,但提供更簡潔且更自然的語法。特別是,您不需要將繫結標記協助程式 Razor 的範本程式碼的任何 C# 程式碼。相反地,它們看起來像是擴充的 HTML 語法的項目。標記協助程式的範例如下:

<environment names="Development">
  <script src="~/content/scripts/yourapp.dev.js" />
</environment>
<environment names="Staging, Production">
  <script src="~/content/scripts/yourapp.min.js" 
    asp-append-version="true" />
</environment>

環境標記項目不是逐字發出給瀏覽器。相反地,其整個子樹狀結構是由能夠讀取屬性,並檢查及修改目前的 HTML 樹狀結構的標記協助程式元件的已剖析的伺服器端。在此範例中,標記協助程式負責環境項目比對的名稱屬性的內容目前 ASP.NET Core 環境,並發出只適用於指令碼項目。此外,會檢查尋找 asp 附加版本自訂屬性的樹狀結構的另一個標記協助程式處理的指令碼項目。如果找不到,正在產生的實際 URL 會附加以確保永遠不會快取已連結之資源的時間戳記。

標記協助程式是 C# 類別繼承自基底類別的機器碼更多,或以宣告方式繫結至標記項目和屬性。每個所要使用標記協助程式的 Razor 檔案必須將它們使用 @addTagHelper 指示詞宣告。指示詞只會註冊標記協助程式類別,從指定的.NET Core 組件。@AddTagHelper 指示詞可能會出現在個別的 Razor 檔案,但更常則是放在 _ViewImports.cshtml 檔案,並會全域套用至所有的檢視:

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

屬性和項目辨識為標記協助程式可能會也強調 Visual Studio 中使用特殊的色彩。ASP.NET Core 隨附的預先定義的標記協助程式,您可以在幾個類別群組的完整封包。一些會影響您可以在 Razor 範本中,例如表單、 輸入、 文字區域,會有標籤,並選取特定的 HTML 項目。一些協助程式改為存在以簡化及自動顯示在表單中的驗證訊息。所有預先定義的標記協助程式共用 asp-* 名稱前置詞。詳細資訊,請參閱bit.ly/2w3BSS2

標記協助程式協助保持 Razor 原始碼,很容易閱讀和精簡。這麼一來,會有任何理由,若要避免使用協助程式。整體來說,我會建議使用標記協助程式自動化的冗長而重複區塊的標記程式碼,撰寫,而不是建立像檢視特定語言的任何項目。使用標記協助程式的多,事實上,您磁碟機越自己遠離純 HTML,更耗費資源進行轉譯的 HTML 檢視。標記協助程式是一項很棒的技術,但是它們代表表現和伺服器端轉譯的成本之間的取捨。說的優點,也很值得您注意標記協助程式,並不會讓您輕鬆地能開啟標記協助程式在任何 HTML 編輯器中使用 Razor 檔案,而不會產生剖析問題變更整體標記語法。也是難以如此 HTML helper。

檢視元件

就技術上來說,檢視元件是獨立的元件,包括邏輯和檢視。在 ASP.NET Core 它們來取代傳統 ASP.NET MVC 5 中的子系動作。您參考的檢視,封鎖 Razor 檔案透過 C# 中的元件,並將其傳遞所需的任何輸入的資料:

@await Component.InvokeAsync("LatestNews", new { count = 4 })

就內部而言,檢視元件會執行自己的邏輯、 處理傳入的資料,並且傳回檢視轉譯。沒有預先定義的檢視元件有 ASP.NET Core,這表示它們會建立嚴格的應用程式為基礎。上一行的程式碼呈現標記在概念上類似於部分檢視的已封裝區塊 LatestNews 檢視元件。部分檢視和檢視元件之間的差異是在內部實作。部分檢視是以純文字的 Razor 範本會選擇性地接收輸入的資料,並結合,它由其中 HTML 範本中。部分檢視不應該有其本身除了格式化和轉譯的任何行為。

檢視元件是更趨精密完美的部分檢視表單。選擇性地檢視元件會接收純文字輸入的參數,通常用來擷取及處理其資料。之後,資料就會合併在內嵌 Razor 範本中,很多部分檢視的行為的方式。不過,檢視元件會在實作快速,因為它未通過執行方式子動作控制器管道列。這表示沒有任何模型繫結,而且沒有動作篩選條件。

整體來說,檢視元件做貴族目的協助化檢視,使它產生的相異且自我提出 widget 組合。這點是拉鋸。具有分割成不同且更獨立的元件檢視似乎便利的方式,以將工作組織可能使其更平行有不同的開發人員負責的各個部分。不過,檢視元件不會加快在所有情況下的項目。所有這取決於每個元件的用途在內部。當討論檢視元件,以及複合 UI 模式下願景時,您通常會看到與服務導向的大型系統的架構,例如,,而這是完全正確。

不過,當您盲目地使用元件,以及整合的內容中的模式,壓縮系統檢視,您可能會得到未最佳化的查詢邏輯。其資料,產生重複的查詢和不必要的資料庫流量可能會查詢每個元件。檢視元件可以用在此案例中,但您應該考慮快取層級,若要避免不正確的結果。

將資料傳遞至檢視

有三個不同且非獨佔方式將資料傳遞至 Razor 檢視 (除了透過 DI @ 插入指示詞)。您可以使用其中兩個內建字典 — 別的 ViewData 或 ViewBag — 或您可以使用強型別的檢視模型類別。從純功能性觀點來看,這種方法之間有任何差異,甚至是從效能觀點來看,差別在於可不予理會。

從設計觀點來看,不過,建議的單一通道檢視模型方法。任何 Razor 檢視應該有單一資料來源,而這是檢視模型物件。這種方法會要求您檢視模型、 支付特別注意的基底類別的設計,而且您避免使用字典和甚至 @ 插入指示詞。

我知道這種方法聽起來嚴格,但其來自經驗。即使在檢視中呼叫 DateTime.Now 很危險,當它將資料插入至可能不是抽象的應用程式的檢視。DateTime.Now 表示時間的伺服器,不是應用程式的時間。這是取決於其作業的當日時間的任何應用程式的問題。若要避免這類的設陷,花費一些時間規畫的一般資料,則必須先在所有檢視中檢視模型類別的設計。此外,請務必一律傳遞資料 — 任何資料,透過模型的檢視,以避免字典和 DI 盡量。速度會使用字典和 DI,而不是在速度稍後必須重整網域中某些功能的大型應用程式時。DI 檢視中的是很棒的一種技術,但它應該搭配不只是 salt 的一個資料粒度。

總結

檢視是 Web 應用程式的基礎。ASP.NET Core 檢視都處理結果的範本檔案 — 通常是 Razor 的範本檔案 — 的混合資料提供由呼叫端,大部分通常是控制器方法。在本文中,我嘗試比較各種適用於建立檢視,並將資料傳遞給它們的方法。大部分的 ASP.NET Core 文獻強調標記協助程式和檢視元件和甚至 Razor 頁面和 DI 的角色在檢視中。這些都是令人信服的所有資源,務必不盲目地,使用它們,因為它們已自然可以產生某些錯誤的結果,如果您不小心的缺點。


Dino Esposito* 是作者"MICROSOFT.NET:架構的企業應用程式 」 (Microsoft Press,2014年) 和"程式設計 ASP.NET Core"(Microsoft Press,2018年)。Pluralsight 作者及開發人員主張在 JetBrains,Esposito 共用 Twitter 上的軟體願景: @despos。*

非常感謝下列 Microsoft 技術專家檢閱這篇文章:Steve Smith


MSDN Magazine 論壇中的這篇文章的討論