在 ASP.NET Core MVC 中處理控制器請求

作者:Steve SmithScott Addie

控制器、動作和動作結果是開發人員使用 ASP.NET Core MVC 建置應用程式的基礎部分。

什麼是控制器?

控制器是用來定義和分組一組動作。 動作 (或「動作方法」) 是控制器上處理要求的方法。 控制器會以邏輯方式將類似動作群組在一起。 這項動作彙總允許統一套用一組通用規則 (例如路由、快取和授權)。 要求會被透過路由對應到動作。 控制器會根據每個要求進行啟動和處置。

依照慣例,控制器類別:

  • 位於專案的根層級 Controllers 資料夾中。
  • 繼承自 Microsoft.AspNetCore.Mvc.Controller

控制器是至少下列其中一個條件為 true 的可具現化類別 (通常為公用):

  • 類別名稱的尾碼為 Controller
  • 類別繼承自名稱尾碼為 Controller 的類別。
  • [Controller] 屬性會套用至該類別。

控制器類別不得具有相關聯的 [NonController] 屬性。

控制器應該遵循明確相依性準則。 有幾種方法可以實作此準則。 如果多個控制器動作需要相同的服務,請考慮使用建構函式插入來要求這些相依性。 如果只有單一動作方法需要服務,請考慮使用動作插入來要求相依性。

Model-View-Controller模式中,控制器負責對請求的初步處理以及對模型的具現化。 一般而言,應該在模型內執行商業決策。

控制器會取用模型的處理結果(如果有的話),並返回對應的視圖及其相關聯的數據,或 API 調用結果。 深入了解 ASP.NET Core MVC 概觀ASP.NET Core MVC 與 Visual Studio 使用者入門

控制器是「UI 層級」抽象概念。 其負責確保要求資料有效,並選擇應該傳回的檢視 (或 API 的結果)。 在構造良好的應用程式中,不會直接包括資料存取或商務邏輯。 相反地,控制器會將這些責任委派給相關的服務。

定義動作

控制器上的公用方法 (不包括具有 [NonAction] 屬性的項目) 就是動作。 動作上的參數會繫結至要求資料,並使用模型繫結進行驗證。 繫結模型的所有項目都會進行模型驗證。 ModelState.IsValid 屬性值指出模型繫結和驗證是否成功。

動作方法應該包含將要求對應至業務需求的邏輯。 商務關注應該一般呈現為控制器透過相依性插入存取的服務。 動作接著會將商務動作的結果對應至應用程式狀態。

操作可以回傳任何東西,但它們經常回傳一個實例IActionResult(或對於非同步方法為Task<IActionResult>),用於產生回應。 動作方法負責選擇「回應類型」。 動作結果「執行回應」

控制器輔助方法

控制器通常繼承自 Controller,但這不是必要的。 衍生自 Controller 提供對三種類別的協助程式方法的存取:

1. 會導致空白回應主體的方法

因為回應主體缺少可描述的內容,所以未包括 Content-Type HTTP 回應標頭。

此類別內有兩種結果類型:「重新導向」和「HTTP 狀態碼」。

  • HTTP 狀態碼

    此類型會傳回 HTTP 狀態碼。 此類型的一些協助程式方法是 BadRequestNotFoundOk。 例如,return BadRequest(); 在執行時會產生 400 狀態碼。 當方法如 BadRequestNotFoundOk 被多載時,就不再適合作為 HTTP 狀態碼回應器,因為會執行內容交涉。

  • 重新導向

    此類型會返回一個動作或目的地的重新導向(使用 RedirectLocalRedirectRedirectToActionRedirectToRoute)。 例如,return RedirectToAction("Complete", new {id = 123}); 會重新導向至 Complete,並傳遞匿名物件。

    「重新導向」結果類型主要的不同在於新增了 Location HTTP 回應標頭,而非像「HTTP 狀態碼」類型。

2. 方法:導致具有預先定義內容類型的非空回應主體

此類別中的大多數協助程式方法包括 ContentType 屬性,可讓您設定 Content-Type 回應標頭來描述回應本文。

此類別內有兩種結果類型:檢視格式化回應

  • 檢視

    此類型回傳一個視圖,使用模型來渲染 HTML。 例如,return View(customer); 會將模型傳遞至資料繫結的視圖。

  • 格式化回應

    此類型會傳回 JSON 或類似的資料交換格式,以特定方式來代表物件。 例如,return Json(customer); 會將所提供的物件序列化為 JSON 格式。

    此類型的其他通用方法包括 FilePhysicalFile。 例如 return PhysicalFile(customerFilePath, "text/xml"); 會傳回 PhysicalFileResult

3. 方法生成一個經與用戶端協商的內容類型格式化的非空回應正文

此類別普遍稱為內容交涉內容協商會在動作傳回ObjectResult類型或非IActionResult實作的其他項目時套用。 傳回非 IActionResult 實作的動作 (例如,object) 也會傳回「格式化回應」。

此類型的一些協助程式方法包括 BadRequestCreatedAtRouteOk。 這些方法的範例分別包括 return BadRequest(modelState);return CreatedAtRoute("routename", values, newobject);return Ok(value);。 請注意,只有在傳遞值時,BadRequestOk 才會執行內容交涉;如果未傳遞值,則會改成作為「HTTP 狀態碼」結果類型。 相反地,CreatedAtRoute 方法一律會執行內容協商,因為其所有的重載方法都需要傳遞一個值。

跨領域關注

應用程式通常會共用其工作流程的各部分。 範例包括需要驗證購物車存取權的應用程式,或快取某些頁面上資料的應用程式。 若要在動作方法之前或之後執行邏輯,請使用 filter。 在交叉關注上使用篩選可減少重複。

大部分的篩選屬性 (例如 [Authorize]) 可以套用至控制器或動作層級 (視所需的細微性層級而定)。

錯誤處理和回應快取通常是跨領域關注:

許多跨領域關注都可以使用篩選或自訂中介軟體進行處理。