1. 程式人生 > >ASP.NET Core 中文文件 第四章 MVC(3.9)檢視元件

ASP.NET Core 中文文件 第四章 MVC(3.9)檢視元件

章節:

介紹檢視元件

檢視元件是 ASP.NET Core MVC 中的新特性,與區域性檢視相似,但是它們更加的強大。檢視元件不使用模型繫結,只取決於呼叫它時所提供的資料。檢視元件有以下特點:

  • 渲染一個塊,而不是整個響應
  • 在控制器和檢視之間同樣包含了關注點分離和可測試性帶來的好處
  • 可以擁有引數和業務邏輯
  • 通常從佈局頁呼叫

檢視元件可以用在任何需要重複邏輯且對區域性檢視來說過於複雜的情況,比如:

  • 動態導航選單
  • 標籤雲 (需要從資料庫查詢時)
  • 登入面板
  • 購物車
  • 最近發表的文章
  • 一個典型部落格的側邊欄內容
  • 會在所有頁面渲染的登入面板,根據使用者登入狀態顯示登入或者登出

一個 檢視元件 包含兩個部分,類(通常派生自 ViewComponent

)和它返回的結果(通常是一個檢視)。類似控制器,檢視元件可以是 POCO 型別,但是大部分開發者想要使用派生自 ViewComponent 的方法和屬性。

建立檢視元件

這個章節包含建立檢視元件的高階需求。在稍後的文章中,我們將詳細地檢查每一個步驟,並建立一個檢視元件。

檢視元件類

一個檢視元件類可以由以下任何一個方式建立:

  • 派生自 ViewComponent
  • 使用 [ViewComponent] 特性裝飾一個類,或者這個類的派生類。
  • 建立一個類,並以 ViewComponent 作為字尾。

如同控制器一樣,檢視元件必須是公開的,非巢狀的,以及非抽象的類。檢視元件名稱是類名並去掉“ViewComponent”字尾。也可以通過

ViewComponentAttribute.Name 屬性進行明確的指定。

一個檢視元件類:

  • 完全支援建構函式依賴注入
  • 不參與控制器生命週期,意味著你不能在檢視元件中使用過濾器

檢視元件方法

檢視元件在 InvokeAsync 方法中中定義邏輯,並返回 [IViewComponentResultIViewComponentResult。引數直接來自檢視元件的呼叫,而不是來自模型繫結。檢視元件從來不直接處理請求。通常檢視元件初始化模型並通過呼叫 View方法傳遞它到檢視。總之,檢視元件方法有以下特點:

  • 定義一個 InvokeAsync 方法並返回 IViewComponentResult
  • 通常初始化模型並通過呼叫ViewComponent View方法傳遞它到檢視
  • 引數來自呼叫方法,而不是 HTTP,沒有模型繫結
  • 不可直接作為 HTTP 終結點,它們從你的程式碼中呼叫(通常在檢視中)。檢視元件從不處理請求
  • 過載的簽名,而不是當前 HTTP 請求中的任何細節

檢視搜尋路徑

執行時對檢視的搜尋路徑如下:

  • Views//Components//
  • Views/Shared/Components//

檢視元件預設的檢視名是 Default,意味著通常你的檢視檔案會命名為 Default.cshtml。當你建立檢視元件結果或者呼叫 View 方法的時候,你可以指定不同的檢視名。

我們建議你命名檢視檔案為 Default.cshtml 並且使用 Views/Shared/Components// 路徑。在這個例子中使用的 PriorityList 檢視元件使用了 Views/Shared/Components/PriorityList/Default.cshtml 這個路徑。

呼叫檢視元件

要使用檢視元件,從檢視中呼叫 @Component.InvokeAsync("檢視元件名", <匿名型別引數>)。引數將傳遞給 InvokeAsync 方法。在文章中開發的 PriorityList 檢視元件被 Views/Todo/Index.cshtml 檢視檔案呼叫。在下面,使用了兩個引數呼叫 InvokeAsync 方法:

@await Component.InvokeAsync("PriorityList", new { maxPriority = 2, isDone = false })

從控制器直接呼叫檢視元件

檢視元件通常從檢視中呼叫,但是你也可以從控制器方法中直接呼叫。當檢視元件沒有像控制器一樣定義終結點時,你可以簡單實現一個控制器的 Action ,並使用一個 ViewComponentResult作為返回內容。

在這例子中,檢視元件通過控制器直接呼叫:

 public IActionResult IndexVC()
  {
      return ViewComponent("PriorityList", new { maxPriority = 3, isDone = false });
  }

演練:建立一個簡單的檢視元件

下載,生成並測試啟動程式碼。這是一個簡單的專案,使用一個 Todo 控制器來顯示 Todo 項列表。

新增一個檢視元件類

建立一個 ViewComponents 資料夾並新增下面的 PriorityListViewComponent 類。

using Microsoft.AspNet.Mvc;
using Microsoft.Data.Entity;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ViewComponentSample.Models;

namespace ViewComponentSample.ViewComponents
{
    public class PriorityListViewComponent : ViewComponent
    {
        private readonly ToDoContext db;

        public PriorityListViewComponent(ToDoContext context)
        {
            db = context;
        }

        public async Task<IViewComponentResult> InvokeAsync(
        int maxPriority, bool isDone)
        {
            var items = await GetItemsAsync(maxPriority, isDone);
            return View(items);
        }
        private Task<List<TodoItem>> GetItemsAsync(int maxPriority, bool isDone)
        {
            return db.ToDo.Where(x => x.IsDone == isDone &&
                                 x.Priority <= maxPriority).ToListAsync();
        }       
    }
}

程式碼註釋:

  • 檢視元件類可以被放在專案中 任何 資料夾內。
  • 因為類命名為 PriorityListViewComponent,以 ViewComponent 作為字尾結束,在執行時會從檢視中使用 "PriorityList" 字串來引用元件類。我會在後面詳細解釋。
  • [ViewComponent] 特性可以改變被用來引用檢視元件的名字。比如,我們可以命名類為 XYZ,然後應用 ViewComponent 特性:
[ViewComponent(Name = "PriorityList")]
public class XYZ : ViewComponent
  • 上面的 [ViewComponent] 特性告知檢視元件選擇器在尋找與元件相關的檢視時使用名字 PriorityList,並且在從檢視中引用元件類時使用 "PriorityList" 字串。我會在後面詳細解釋。
  • 元件使用依賴注入使得資料上下文可用。
  • InvokeAsync 暴露一個可以在檢視中呼叫的方法,並且它可以接受任意數量的引數。
  • InvokeAsync 方法返回沒有完成並優先順序小於等於 maxPriorityToDo 項的集合。

建立檢視元件 Razor 檢視

  1. 建立 Views/Shared/Components 資料夾。這個資料夾 必須 命名為 Components
  2. 建立 Views/Shared/Components/PriorityList 資料夾。這個資料夾必須和檢視元件類名字匹配,或者是類名去掉字尾(如果我們遵循了約定並且使用 ViewComponent 作為類名字尾)。如果你使用 ViewComponent 特性,類名需要匹配特性中指定的名字。
  3. 建立一個 Views/Shared/Components/PriorityList/Default.cshtml Razor 檢視。
@model IEnumerable<ViewComponentSample.Models.TodoItem>

<h3>Priority Items</h3>
<ul>
    @foreach (var todo in Model)
    {
        <li>@todo.Name</li>
    }
</ul>

Razor 檢視取一組 TodoItem 並顯示它們。如果檢視元件的 InvokeAsync 方法沒有傳遞檢視名(就像我們例子中),按照約定會使用 Default 作為檢視名。在教程的後面部分,我會告訴你如何傳遞檢視的名稱。為特定控制器重寫預設的樣式,新增一個檢視到特定控制器的檢視資料夾(比如 Views/Todo/Components/PriorityList/Default.cshtml)。

如果檢視元件是特定控制器的,你可以新增到特定控制器資料夾(Views/Todo/Components/PriorityList/Default.cshtml)。

  1. Views/Todo/index.cshtml 檔案底部新增一個 div 包含呼叫 PriorityList 元件:
  }
</table>
<div >
    @await Component.InvokeAsync("PriorityList", new { maxPriority = 2, isDone = false })
</div>

標記 @Component.InvokeAsync 展示了呼叫檢視元件的語法。第一個引數是我們想要呼叫的元件名。隨後的引數傳遞給元件。InvokeAsync 可以接受任意數量的引數。

下面的圖片顯示了 Priority 項:

你也可以從控制器直接呼叫檢視元件:

public IActionResult IndexVC()
{
    return ViewComponent("PriorityList", new { maxPriority = 3, isDone = false });
}

指定檢視名

一個複雜的檢視元件在某些條件下可能需要指定非預設的檢視。下面的程式碼展示如何從 InvokeAsync 方法中指定 "PVC" 檢視。更新 PriorityListViewComponent 類中的 InvokeAsync 方法。

public async Task<IViewComponentResult> InvokeAsync(int maxPriority, bool isDone)
{
    string MyView = "Default"; // 手動高亮
    // If asking for all completed tasks, render with the "PVC" view. // 手動高亮
    if (maxPriority > 3 && isDone == true) // 手動高亮
    {   // 手動高亮
        MyView = "PVC"; // 手動高亮
    }   // 手動高亮
    var items = await GetItemsAsync(maxPriority, isDone);
    return View(MyView, items);
}

複製 Views/Shared/Components/PriorityList/Default.cshtml 檔案到一個檢視中並命名為 Views/Shared/Components/PriorityList/PVC.cshtml。新增一個標題到 PVC 檢視來表明正在使用此檢視。

@model IEnumerable<ViewComponentSample.Models.TodoItem>

<h2> PVC Named Priority Component View</h2> // 手動高亮
<h4>@ViewBag.PriorityMessage</h4>
<ul>
    @foreach (var todo in Model)
    {
        <li>@todo.Name</li>
    }
</ul>

更新 Views/TodoList/Index.cshtml

</table>

<div>
    @await Component.InvokeAsync("PriorityList", new { maxPriority = 4, isDone = true })
</div>

執行應用程式並驗證 PVC 檢視。

如果 PVC 檢視沒有渲染,請驗證你是否使用 4 或者更高 priority 引數來呼叫檢視元件。

檢查檢視路徑

  1. 改變 priority 引數到 3 或者更低,使得不返回優先順序檢視。
  2. 暫時重新命名 Views/Todo/Components/PriorityList/Default.cshtmlTemp.cshtml
  3. 測試應用程式,你將得到以下錯誤:

    An unhandled exception occurred while processing the request.

    InvalidOperationException: The view 'Components/PriorityList/Default'
    was not found. The following locations were searched:
    /Views/ToDo/Components/PriorityList/Default.cshtml
    /Views/Shared/Components/PriorityList/Default.cshtml.
    Microsoft.AspNetCore.Mvc.ViewEngines.ViewEngineResult.EnsureSuccessful()

  4. 複製 Views/Shared/Components/PriorityList/Default.cshtmlViews/Todo/Components/PriorityList/Default.cshtml
  5. 新增一些標記到 Todo 檢視元件檢視來表明檢視是來自 Todo 資料夾。
  6. 測試 非共享 元件檢視。

避免魔法字串

如果你想編譯時安全你可以用類名替換硬編碼檢視元件名。建立檢視元件不以 "ViewComponent" 作為字尾:

using Microsoft.AspNet.Mvc;
using Microsoft.Data.Entity;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ViewComponentSample.Models;

namespace ViewComponentSample.ViewComponents
{
    public class PriorityList : ViewComponent // 手動高亮
    {
        private readonly ToDoContext db;

        public PriorityList(ToDoContext context) // 手動高亮
        {
            db = context;
        }

        public async Task<IViewComponentResult> InvokeAsync(
        int maxPriority, bool isDone)
        {
            var items = await GetItemsAsync(maxPriority, isDone);
            return View(items);
        }
        private Task<List<TodoItem>> GetItemsAsync(int maxPriority, bool isDone)
        {
            return db.ToDo.Where(x => x.IsDone == isDone &&
                                 x.Priority <= maxPriority).ToListAsync();
        }
    }
}

新增一個 using 語句到你的 Razor 檢視檔案並使用 nameof 操作符:

@using ViewComponentSample.Models
@using ViewComponentSample.ViewComponents
@model IEnumerable<TodoItem>

<h2>ToDo nameof</h2>
<!-- Markup removed for brevity.  -->
    }
</table>

<div>

    @await Component.InvokeAsync(nameof(PriorityList), new { maxPriority = 4, isDone = true })
</div>

附加的資源

返回目錄

相關推薦

ASP.NET Core 中文 MVC3.9檢視元件

章節: 介紹檢視元件 檢視元件是 ASP.NET Core MVC 中的新特性,與區域性檢視相似,但是它們更加的強大。檢視元件不使用模型繫結,只取決於呼叫它時所提供的資料。檢視元件有以下特點: 渲染一個塊,而不是整個響應 在控制器和檢視之間同樣包含了關注點分離和可測試性帶來的好處 可以擁有引數和業務邏

ASP.NET Core 中文 MVC3.8檢視中的依賴注入

ASP.NET Core 支援在檢視中使用 依賴注入 。這將有助於提供檢視專用的服務,比如本地化或者僅用於填充檢視元素的資料。你應該儘量保持控制器和檢視間的關注點分離(separation of concerns)。你的檢視所顯示的大部分資料應該從控制器傳入。 章節: 一個簡單的示例 你可以使用 @i

ASP.NET Core 中文 MVC3.7 區域性檢視partial

ASP.NET Core MVC 支援區域性檢視,當你需要在多個不同檢視間重用同一個頁面部件時會顯得特別有用。 什麼是區域性檢視? 區域性檢視是在其它檢視中被渲染的檢視。區域性檢視執行後生成的 HTML 結果會被渲染到呼叫方檢視或父檢視中。跟檢視檔案一樣,區域性檢視檔案也使用 .cshtml 作為副檔名。

ASP.NET Core 中文 MVC4.6Areas區域

Areas 是 ASP.NET MVC 用來將相關功能組織成一組單獨名稱空間(路由)和資料夾結構(檢視)的功能。使用 Areas 建立層次結構的路由,是通過新增另一個路由引數 area 到 Controller 和 action。 Areas 提供了一種把大型 ASP.NET Core MVC Web 應用

ASP.NET Core 中文 MVC4.2控制器操作的路由

ASP.NET Core MVC 使用路由 中介軟體 來匹配傳入請求的 URL 並對映到具體的操作。路由通過啟動程式碼或者特性定義。路由描述 URL 路徑應該如何匹配到操作。路由也同樣用於生成響應中返回的 URL(用於連結)。 這篇文章將解釋 MVC 和路由之間的相互作用,以及典型的 MVC 應用程式如何使

ASP.NET Core 中文 MVC4.1Controllers, Actions 和 Action Results

Action 和 action result 是開發者使用 ASP.NET MVC 構建應用程式的基礎部分。 什麼是 Controller 在 ASP.NET MVC 中, 控制器( Controller  )用於定義和聚合操作(Action)的一個集合。操作( 或操作方法 )是控制器中處理入站請求的一個方

ASP.NET Core 中文 MVC4.4依賴注入和控制器

ASP.NET Core MVC 控制器應通過它們的構造器明確的請求它們的依賴關係。在某些情況下,單個控制器的操作可能需要一個服務,在控制器級別上的請求可能沒有意義。在這種情況下,你也可以選擇將服務作為 action 方法的引數。 章節: 依賴注入 依賴注入(Dependency injection,

ASP.NET Core 中文 MVC4.5測試控制器邏輯

ASP.NET MVC 應用程式的控制器應當小巧並專注於使用者介面。涉及了非 UI 事務的大控制器更難於測試和維護。 章節: 為什麼要測試控制器 控制器是所有 ASP.NET Core MVC 應用程式的核心部分。因此,你應當確保它們的行為符合應用的預期。 自動化測試可以為你提供這樣的保障並能夠在進入生

ASP.NET Core 中文 MVC2.3格式化響應資料

ASP.NET Core MVC 內建支援對相應資料(response data)的格式化,用來修正格式或生成客戶端指定的格式。 特定格式的操作結果 某些操作結果(Action result)的型別是指定的特定格式,比如 JsonResult 或 ContentResult。Action 可以返回格式化為

ASP.NET Core 中文 MVC01ASP.NET Core MVC 概覽

ASP.NET Core MVC 是使用模型-檢視-控制器(Model-View-Controller)設計模式構建網頁應用與 API 的豐富的框架。 什麼是 MVC 模式? 模型-檢視-控制器(MVC)架構模式將一個應用區分為三部分主要元件:模型、檢視、與控制器。這種模式有助實現關注分離。使用這種模式,使

ASP.NET Core 中文 MVC4.3過濾器

ASP.NET MVC 過濾器 可在執行管道的前後特定階段執行程式碼。過濾器可以配置為全域性有效、僅對控制器有效或是僅對 Action 有效。 過濾器如何工作? 不同的過濾器型別會在執行管道的不同階段執行,因此它們各自有一套適用場景。根據你實際要解決的問題以及在請求管道中執行的位置來選擇建立不同的過濾器。

ASP.NET Core 中文 測試5.2整合測試

整合測試確保應用程式的元件組裝在一起時正常工作。 ASP.NET Core支援使用單元測試框架和可用於處理沒有網路開銷請求的內建測試的網路主機整合測試。 章節: 整合測試介紹 整合測試驗證應用程式不同的部位是否正確地組裝在一起。不像單元測試,整合測試經常涉及到應用基礎設施,如資料庫,檔案系統,網路資源

ASP.NET Core 中文 原理2中介軟體

章節: 什麼是中介軟體 中介軟體是用於組成應用程式管道來處理請求和響應的元件。管道內的每一個元件都可以選擇是否將請求交給下一個元件、並在管道中呼叫下一個元件之前和之後執行某些操作。請求委託被用來建立請求管道,請求委託處理每一個 HTTP 請求。 請求委託通過使用 IApplicationBuilder

ASP.NET Core 中文 原理6全球化與本地化

使用 ASP.NET Core 建立一個多語言版本的網站有助於你吸引到更多的使用者,ASP.NET Core 提供服務和中介軟體來支援本地化語言和文化。 國際化涉及 全球化 和 本地化。全球化是為了應用程式支援不同文化而設計的。全球化增加了對特定地理區域的語言文字的輸入、顯示和輸出的支援。 本地化是針對一個

ASP.NET Core 中文 原理11在多個環境中工作

ASP.NET Core 介紹了支援在多個環境中管理應用程式行為的改進,如開發(development),預演(staging)和生產(production)。環境變數用來指示應用程式正在執行的環境,允許應用程式適當地配置。 章節: 開發,預演,生產 ASP.NET Core 引用了一個特定的環境變數

ASP.NET Core 中文 原理4路由

路由是用來把請求對映到路由處理程式。應用程式一啟動就配置了路由,並且可以從URL中提取值用於處理請求。它還負責使用 ASP.NET 應用程式中定義的路由來生成連結。 這份文件涵蓋了初級的ASP.NET核心路由。對於 ASP.NET 核心 MVC 路由, 請檢視 Routing to Controller A

ASP.NET Core 中文 原理13管理應用程式狀態

在 ASP.NET Core 中,有多種途徑可以對應用程式的狀態進行管理,取決於檢索狀態的時機和方式。本文簡要介紹幾種可選的方式,並著重介紹為 ASP.NET Core 應用程式安裝並配置會話狀態支援。 應用程式狀態的可選方式 應用程式狀態 指的是用於描述應用程式當前狀況的任意資料。包括全域性的和使用者特

ASP.NET Core 中文 原理1應用程式啟動

ASP.NET Core 為你的應用程式提供了處理每個請求的完整控制。Startup 類是應用程式的入口(entry point),這個類可以設定配置(configuration)並且將應用程式將要使用的服務連線起來。開發人員可以在 Startup 類中配置請求管道,該管道將用於處理應用程式的所有請求。 章

ASP.NET Core 中文 原理16.NET開放Web介面OWIN

ASP.NET Core 支援 OWIN(即 Open Web Server Interface for .NET 的首字母縮寫),OWIN的目標是用於解耦Web Server和Web Application。此外, OWIN為中介軟體定義了一個標準方法用來處理單個請求以及相關聯的響應。ASP.NET Co

ASP.NET Core 中文 原理17為你的伺服器選擇合適版本的.NET框架

ASP.NET Core基於 .NET Core 專案模型,它支援構建能夠執行在 Windows、Mac和 Linux 上的跨平臺應用程式。當您構建一個 .Net Core 專案的時候,您可以選擇一種 .NET框架來構建您的應用程式,.NET Framework (CLR)、 .NET Core (Core