練習 - 新增控制器
控制器 是一種公用類別,其中具有一或多個稱為動作的公用方法。 依照慣例,控制器置於專案根目錄的 Controllers 目錄中。 動作會公開為 Web API 控制器內的 HTTP 端點。
建立控制器
在 Visual Studio Code 中選取 Controllers 資料夾,並新增名為 PizzaController.cs 的新檔案。
即會在 Controllers 目錄中建立名為 PizzaController.cs 的空類別檔案。 Controllers 目錄名稱是一種慣例。 此目錄名稱來自 Web API 使用的模型-檢視-控制器架構。
注意
依照慣例,控制器類別名稱的字首會加上 Controller。
將下列程式碼新增至 Controllers/PizzaController.cs。 儲存您的變更。
using ContosoPizza.Models; using ContosoPizza.Services; using Microsoft.AspNetCore.Mvc; namespace ContosoPizza.Controllers; [ApiController] [Route("[controller]")] public class PizzaController : ControllerBase { public PizzaController() { } // GET all action // GET by Id action // POST action // PUT action // DELETE action }
如您先前所了解的,這個類別衍生自
ControllerBase
,也就是在 ASP.NET Core 中使用 HTTP 要求的基底類別。 其也包含您所了解到的兩個標準屬性:[ApiController]
和[Route]
。 如同先前一樣,[Route]
屬性會定義[controller]
權杖的對應。 由於此控制器類別已命名為PizzaController
,因此對https://localhost:{PORT}/pizza
的要求會由此控制器處理。
取得所有披薩
您需要實作的第一個 REST 指令動詞是 GET
,在其中用戶端可以從 API 取得所有披薩。 您可以使用內建 [HttpGet]
屬性來定義從我們的服務傳回披薩的方法。
用下列程式碼取代 Controllers/PizzaController.cs 中的 // GET all action
註解:
[HttpGet]
public ActionResult<List<Pizza>> GetAll() =>
PizzaService.GetAll();
上述動作:
- 只回應
[HttpGet]
屬性表示的 HTTPGET
動詞。 - 傳回
List<Pizza>
類型的ActionResult
執行個體。ActionResult
類型是 ASP.NET Core 中所有動作結果的基底類別。 - 查詢所有披薩的服務,並自動傳回資料,其中具有
application/json
的Content-Type
值。
取出單一披薩
用戶端可能也會想要要求特定披薩的相關資訊,而不是整個清單。 您可以實作需要 id
參數的另一個 GET
動作。 您可以使用內建 [HttpGet("{id}")]
屬性來定義從我們的服務傳回披薩的方法。 路由邏輯會註冊 [HttpGet]
(沒有 id
) 和 [HttpGet("{id}")]
(有 id
) 來作為兩個不同的路由。 接著可以撰寫個別的動作來取出單一項目。
用下列程式碼取代 Controllers/PizzaController.cs 中的 // GET by Id action
註解:
[HttpGet("{id}")]
public ActionResult<Pizza> Get(int id)
{
var pizza = PizzaService.Get(id);
if(pizza == null)
return NotFound();
return pizza;
}
上述動作:
- 只回應
[HttpGet]
屬性表示的 HTTPGET
動詞。 - 需要將
id
參數的值加入 URL 的pizza/
後方。 請記住,控制器層級的[Route]
屬性會定義/pizza
模式。 - 查詢資料庫找出符合所提供
id
參數的披薩。
每個用於上述動作的 ActionResult
執行個體,都會對應至下表中的相應 HTTP 狀態碼:
ASP.NET Core 動作結果 |
HTTP 狀態碼 | 描述 |
---|---|---|
意指 Ok |
200 | 符合所提供 id 參數的產品存在於記憶體內部快取中。產品包含在媒體類型的回應本文中,而此回應本文定義在 accept HTTP 要求標題 (預設為 JSON) 中。 |
NotFound |
404 | 符合所提供 id 參數的產品未存在於記憶體內部快取中。 |
建置並執行新的控制器
執行下列命令來建立並啟動 Web API:
dotnet run
使用 HTTP 檔案測試控制器
開啟 ContosoPizza.http
新增 GET 以在 ### 分隔符號下呼叫
Pizza
端點:GET {{ContosoPizza_HostAddress}}/pizza/ Accept: application/json ###
選取這個新 GET 呼叫上方的 [傳送要求] 命令。
上述命令會以 JSON 格式傳回所有披薩的清單:
HTTP/1.1 200 OK Connection: close Content-Type: application/json; charset=utf-8 Date: Wed, 17 Jan 2024 16:57:09 GMT Server: Kestrel Transfer-Encoding: chunked [ { "id": 1, "name": "Classic Italian", "isGlutenFree": false }, { "id": 2, "name": "Veggie", "isGlutenFree": true } ]
若要查詢單一披薩,您可以提出另一個
GET
要求,但是使用下列命令傳入id
參數:GET {{ContosoPizza_HostAddress}}/pizza/1 Accept: application/json ###
上述命令會傳回具有下列輸出的
Classic Italian
:HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 Date: Fri, 02 Apr 2021 21:57:57 GMT Server: Kestrel Transfer-Encoding: chunked { "id": 1, "name": "Classic Italian", "isGlutenFree": false }
我們的 API 也會處理項目不存在的情況。 請再次呼叫 API,但是使用下列命令傳入無效的披薩
id
參數:GET {{ContosoPizza_HostAddress}}/pizza/5 Accept: application/json ###
上述命令會傳回具有下列輸出的
404 Not Found
錯誤:HTTP/1.1 404 Not Found Content-Type: application/problem+json; charset=utf-8 Date: Fri, 02 Apr 2021 22:03:06 GMT Server: Kestrel Transfer-Encoding: chunked { "type": "https://tools.ietf.org/html/rfc7231#section-6.5.4", "title": "Not Found", "status": 404, "traceId": "00-ec263e401ec554b6a2f3e216a1d1fac5-4b40b8023d56762c-00" }
現在您已完成實作 GET
動詞。 在下一個單元中,您可以將更多動作新增至 PizzaController
以支援披薩資料的 CRUD 作業。
選擇性:使用命令列 HTTP「讀取、求值、輸出」迴圈 (REPL) 測試控制器
藉由從主功能表中選取 [終端機] > [新增終端機],以從 Visual Studio Code 開啟現有的
httprepl
終端機或開啟新的整合式終端機。執行下列命令來連線至 Web API:
httprepl https://localhost:{PORT}
或者,也可以在
HttpRepl
執行期間的任何時候執行下列命令:connect https://localhost:{PORT}
若要查看新推出的
Pizza
端點,請執行下列命令:ls
上述命令會偵測已連線端點上所有可用的 API。 應該會顯示下列程式碼:
https://localhost:{PORT}/> ls . [] Pizza [GET] WeatherForecast [GET]
執行下列命令,以前往
Pizza
端點:cd Pizza
上述命令會顯示
Pizza
端點的可用 API 輸出:https://localhost:{PORT}/> cd Pizza /Pizza [GET]
使用下列命令,在
HttpRepl
中提出GET
要求:get
上述命令會以 JSON 格式傳回所有披薩的清單:
HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 Date: Fri, 02 Apr 2021 21:55:53 GMT Server: Kestrel Transfer-Encoding: chunked [ { "id": 1, "name": "Classic Italian", "isGlutenFree": false }, { "id": 2, "name": "Veggie", "isGlutenFree": true } ]
若要查詢單一披薩,您可以提出另一個
GET
要求,但是使用下列命令傳入id
參數:get 1
上述命令會傳回具有下列輸出的
Classic Italian
:HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 Date: Fri, 02 Apr 2021 21:57:57 GMT Server: Kestrel Transfer-Encoding: chunked { "id": 1, "name": "Classic Italian", "isGlutenFree": false }
我們的 API 也會處理項目不存在的情況。 請再次呼叫 API,但是使用下列命令傳入無效的披薩
id
參數:get 5
上述命令會傳回具有下列輸出的
404 Not Found
錯誤:HTTP/1.1 404 Not Found Content-Type: application/problem+json; charset=utf-8 Date: Fri, 02 Apr 2021 22:03:06 GMT Server: Kestrel Transfer-Encoding: chunked { "type": "https://tools.ietf.org/html/rfc7231#section-6.5.4", "title": "Not Found", "status": 404, "traceId": "00-ec263e401ec554b6a2f3e216a1d1fac5-4b40b8023d56762c-00" }
返回 Visual Studio Code 下拉式清單中的
dotnet
終端機,然後選取鍵盤的 CTRL+C 來關閉 Web API。
現在您已完成實作 GET
動詞。 在下一個單元中,您可以將更多動作新增至 PizzaController
以支援披薩資料的 CRUD 作業。