演習 - コントローラーを追加する

完了

controller は、"アクション" と呼ばれる 1 つまたは複数のパブリック メソッドを含むパブリック クラスです。 規約により、コントローラーはプロジェクト ルートの Controllers ディレクトリに配置します。 アクションは、Web API コントローラー内の HTTP エンドポイントとして公開されます。

コントローラーの作成

  1. Visual Studio Code で Controllers フォルダーを選んで、PizzaController.cs という名前の新しいファイルを追加します。

    Screenshot of Visual Studio Code that shows adding a new file to the Controllers folder.

    PizzaController.cs という名前の空のクラス ファイルが、Controllers ディレクトリに作成されます。 Controllers というディレクトリ名は規約で決まっています。 ディレクトリ名の由来は、Web API で使用している Model-View-Controller アーキテクチャです。

    Note

    規約により、コントローラー クラスの名前には 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
    }
    

    前に学習したように、このクラスは、ASP.NET Core で HTTP 要求を処理するための基底クラスである ControllerBase から派生します。 また、学習した 2 つの標準属性 [ApiController][Route] も含まれます。 前と同様に、[Route] 属性で、[controller] トークンへのマッピングを定義します。 このコントローラー クラスは PizzaController という名前であるため、このコントローラーは https://localhost:{PORT}/pizza への要求を処理します。

すべてのピザを取得する

実装する必要がある最初の REST 動詞は、クライアントが API からすべてのピザを取得できる GET です。 組み込みの [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 のすべてのアクション結果の基本クラスです。
  • サービスに対してすべてのピザのクエリを実行し、Content-Type の値を application/json にしてデータを自動的に返します。

単一のピザを取得する

クライアントは、リスト全体ではなく、特定のピザに関する情報を要求することもあります。 id パラメーターを必要とする別の GET アクションを実装できます。 組み込みの [HttpGet("{id}")] 属性を使用して、このサービスからピザを返すメソッドを定義できます。 ルーティング ロジックで、[HttpGet] (id なし) と [HttpGet("{id}")] (id あり) を 2 つの異なるルートとして登録します。 次に、単一の項目を取得する個別のアクションを記述できます。

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 動詞にのみ応答します。
  • URL セグメントの pizza/ の後に、id パラメーターの値が含まれている必要があります。 コントローラー レベルの [Route] 属性で /pizza パターンが定義されていたことを思い出してください。
  • データベースに対して、指定された id パラメーターに一致するピザのクエリを実行します。

上記のアクションで使用されている ActionResult の各インスタンスは、次の表の対応する HTTP 状態コードにマップされます。

ASP.NET Core
アクションの結果
HTTP 状態コード 説明
Ok が暗示されます 200 指定された id パラメーターに一致する商品が、メモリ内キャッシュに存在します。
商品は、accept HTTP 要求ヘッダーで定義されているメディアの種類で応答本文に含まれます (既定では JSON)。
NotFound 404 指定された id パラメーターに一致する商品が、メモリ内キャッシュに存在しません。

新しいコントローラーをビルドして実行する

次のコマンドを実行して、Web API をビルドして開始します。

```dotnetcli
dotnet run
```

.http ファイルを使用してコントローラーをテストする

  1. ContosoPizza.http を開きます

  2. ### 区切り記号の下で Pizza エンドポイントを呼び出す新しい GET を追加します。

    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. 1 つのピザのクエリを実行するには、別の 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. 既存の httprepl ターミナルを開くか、Visual Studio Code のメイン メニューから [ターミナル]>[新しいターミナル] を選んで新しい統合ターミナルを開きます。

  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. 次のコマンドを使用して、HttpReplGET 要求を行います。

    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. 1 つのピザのクエリを実行するには、別の 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 操作をサポートできます。