練習 - 新增控制器

已完成

控制器 是一種公用類別,其中具有一或多個稱為動作的公用方法。 依照慣例,控制器置於專案根目錄的 Controllers 目錄中。 動作會公開為 Web API 控制器內的 HTTP 端點。

建立控制器

  1. 在 Visual Studio Code 中選取 Controllers 資料夾,並新增名為 PizzaController.cs 的新檔案。

    Visual Studio Code 的螢幕擷取畫面,顯示將新檔案新增至 Controllers 資料夾。

    即會在 Controllers 目錄中建立名為 PizzaController.cs 的空類別檔案。 Controllers 目錄名稱是一種慣例。 此目錄名稱來自 Web API 使用的模型-檢視-控制器架構。

    注意

    依照慣例,控制器類別名稱的字首會加上 Controller

  2. 將下列程式碼新增至 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] 屬性表示的 HTTP GET 動詞。
  • 傳回 List<Pizza> 類型的 ActionResult 執行個體。 ActionResult 類型是 ASP.NET Core 中所有動作結果的基底類別。
  • 查詢所有披薩的服務,並自動傳回資料,其中具有 application/jsonContent-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] 屬性表示的 HTTP GET 動詞。
  • 需要將 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 檔案測試控制器

  1. 開啟 ContosoPizza.http

  2. 新增 GET 以在 ### 分隔符號下呼叫 Pizza 端點:

    GET {{ContosoPizza_HostAddress}}/pizza/
    Accept: application/json
    
    ###
    
  3. 選取這個新 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
        }
    ]   
    
  4. 若要查詢單一披薩,您可以提出另一個 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
    }
    
  5. 我們的 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) 測試控制器

  1. 藉由從主功能表中選取 [終端機] > [新增終端機],以從 Visual Studio Code 開啟現有的 httprepl 終端機或開啟新的整合式終端機。

  2. 執行下列命令來連線至 Web API:

    httprepl https://localhost:{PORT}
    

    或者,也可以在 HttpRepl 執行期間的任何時候執行下列命令:

    connect https://localhost:{PORT}
    
  3. 若要查看新推出的 Pizza 端點,請執行下列命令:

    ls
    

    上述命令會偵測已連線端點上所有可用的 API。 應該會顯示下列程式碼:

     https://localhost:{PORT}/> ls
     .                 []
     Pizza             [GET]
     WeatherForecast   [GET]
    
  4. 執行下列命令,以前往 Pizza 端點:

    cd Pizza
    

    上述命令會顯示 Pizza 端點的可用 API 輸出:

    https://localhost:{PORT}/> cd Pizza
    /Pizza    [GET]
    
  5. 使用下列命令,在 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
          }
      ]
    
  6. 若要查詢單一披薩,您可以提出另一個 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
    }
    
  7. 我們的 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"
    }
    
  8. 返回 Visual Studio Code 下拉式清單中的 dotnet 終端機,然後選取鍵盤的 CTRL+C 來關閉 Web API。

現在您已完成實作 GET 動詞。 在下一個單元中,您可以將更多動作新增至 PizzaController 以支援披薩資料的 CRUD 作業。