演習 - 新しい Razor ページを追加する

完了

前のユニットでは、Contoso Pizza プロジェクトのソース コードを取得し、ホーム ページにいくつかの簡単な変更を加えました。 このユニットでは、新しい Razor ページをプロジェクトに追加します。

Pizza List ページを作成する

新しい Razor ページを作成するには、.NET CLI を使用します。

  1. ターミナルは dotnet watch コマンドによってブロックされているため、エクスプローラーContosoPizza フォルダーを右クリックして別のターミナルを開き、[統合ターミナルで開く] を選択します。

  2. 新しいターミナル ウィンドウで、次のコマンドを入力します。

    dotnet new page --name PizzaList --namespace ContosoPizza.Pages --output Pages
    

    上記のコマンドでは次のことが行われます。

    • ContosoPizza.Pages 名前空間に次の 2 つのファイルを作成します。
      • PizzaList.cshtml - Razor ページ
      • PizzaList.cshtml.cs - 付随する PageModel クラス
    • 両方のファイルがプロジェクトの Pages サブディレクトリに格納されます。
  3. Pages/PizzaList.cshtml で、@{ } コード ブロック内に次のコードを追加します。

    ViewData["Title"] = "Pizza List 🍕";
    

    これにより、ページの <title> 要素が設定されます。

  4. ファイルの末尾に次のコードを追加します。

    <h1>Pizza List 🍕</h1>
    
    <!-- New Pizza form will go here -->
    
    <!-- List of pizzas will go here -->
    

    これによってページに、見出しと、後で追加する機能の 2 つの HTML コメント プレースホルダーが追加されます。

  5. ファイルを保存します。 GitHub Codespaces を使用している場合は、ファイルが自動的に保存されます。

  6. dotnet watch を実行しているターミナルに戻り、Ctrl + R キーを押してアプリを再度読み込んで、新しいファイルを検出します。

ナビゲーション メニューに Pizza List ページを追加する

この時点でページをテストするのが望ましいのですが、ページがまだナビゲーション メニューにリンクされていないため、ブラウザーではページに到達できません。 ここでリンクします。

  1. Pages/Shared/_Layout.cshtml を開きます。

  2. navbar-nav クラスを指定した <ul> 要素 (21 行目から始まる) で、Home および Privacy ページへのリンクを含む <li> 要素に注目してください。 次のコードをリストの末尾に、つまり Privacy リンクを含む <li> 要素の後に追加します。

    <li class="nav-item">
        <a class="nav-link text-dark" asp-area="" asp-page="/PizzaList">Pizza List 🍕</a>
    </li>
    

    これにより、PizzaList ページへのリンクがナビゲーション メニューに追加されます。

  3. ファイルを保存します。 アプリが実行されているブラウザー タブは自動的に更新され、変更が表示されます。 GitHub Codespaces を使用している場合、ファイルは自動的に保存されますが、ブラウザー タブを手動で更新する必要があります。

  4. ナビゲーション メニューの [Pizza List] 🍕 リンクを選択します。 Pizza List ページが表示されます。

PizzaService クラスを依存関係挿入コンテナーに登録する

ピザ一覧ページでは、ピザの一覧を取得するために PizzaService オブジェクトに依存しています。 依存関係の挿入を使用して、PizzaService オブジェクトをページに提供します。 まず、PizzaService クラスをコンテナーに登録します。

  1. Program.cs を開きます。

  2. コンテナーにサービスを追加するセクションで、次のコードを追加します。

    builder.Services.AddScoped<PizzaService>();
    

    このコードで PizzaService クラスを依存関係挿入コンテナーに登録します。 AddScoped メソッドは、HTTP 要求ごとに新しい PizzaService オブジェクトを作成する必要があることを示します。 これで、PizzaService を任意の Razor ページに挿入できます。

  3. ファイルを保存します。 GitHub Codespaces を使用している場合、ファイルは自動的に保存されます。

ピザの一覧を表示する

PizzaService オブジェクトからピザのリストを取得し、プロパティに格納するために、ピザリストページの PageModel クラスを修正してみましょう。

  1. Pages/PizzaList.cshtml.cs を開きます。

  2. 次の using ステートメントをファイルの先頭に追加します。

    using ContosoPizza.Models;
    using ContosoPizza.Services;
    

    これらのステートメントにより、ページで使用する Pizza および PizzaService 型をインポートします。

  3. ContosoPizza.Pages 名前空間ブロック内で、PizzaListModel クラス全体を次のコードに置き換えます。

    public class PizzaListModel : PageModel
    {
        private readonly PizzaService _service;
        public IList<Pizza> PizzaList { get;set; } = default!;
    
        public PizzaListModel(PizzaService service)
        {
            _service = service;
        }
    
        public void OnGet()
        {
            PizzaList = _service.GetPizzas();
        }
    }
    

    上のコードでは以下の操作が行われます。

    • _service という名前の読み取り専用プライベート PizzaService が作成されます。 この変数は、PizzaService オブジェクトへの参照を保持します。
      • readonly キーワードは、コンストラクターで設定された _service 変数の値を後から変更できないことを示します。
    • PizzaList プロパティは、ピザの一覧を保持するように定義されます。
      • IList<Pizza> 型は、PizzaList プロパティが Pizza オブジェクトの一覧を保持することを示します。
      • PizzaListdefault! に初期化されます。これにより、後で初期化されることがコンパイラに示されるため、null safety チェックは必要ありません。
    • コンストラクターは PizzaService オブジェクトを受け取ります。
      • PizzaService オブジェクトは、依存関係の挿入によって提供されます。
    • OnGet メソッドは、PizzaService オブジェクトからピザの一覧を取得し、PizzaList プロパティにそれを保管するように定義されます。

    ヒント

    Null Safety を理解するのにヘルプが必要な場合は、「C# での Null Safety」を参照してください。

  4. ファイルを保存します。 GitHub Codespaces を使用している場合、ファイルは自動的に保存されます。

  5. dotnet watch を実行しているターミナルに戻り、Ctrl + R キーを押して、登録済みサービスと PizzaListModel の新しいコンストラクターを使用してアプリを再度読み込みます。

ピザの一覧を表示する

ページからピザの一覧にアクセスできるようになったので、その一覧を使用して、ページにピザを表示します。

  1. Pages/PizzaList.cshtml を開きます。

  2. コメント `` を、次のコードに置き換えます。

    <table class="table mt-5">
        <thead>
            <tr>
                <th scope="col">Name</th>
                <th scope="col">Price</th>
                <th scope="col">Size</th>
                <th scope="col">Gluten Free</th>
                <th scope="col">Delete</th>
            </tr>
        </thead>
        <tbody>
        @foreach (var pizza in Model.PizzaList)
        {
            <tr>
                <td>@pizza.Name</td>
                <td>@($"{pizza.Price:C}")</td>
                <td>@pizza.Size</td>
                <td>@(pizza.IsGlutenFree ? "✔️" : string.Empty)</td>
                <td>
                    <form method="post" asp-page-handler="Delete" asp-route-id="@pizza.Id">
                        <button class="btn btn-danger">Delete</button>
                    </form>
                </td>
            </tr>
        }
        </tbody>
    </table>
    

    上のコードでは以下の操作が行われます。

    • ピザの一覧を表示する <table> 要素が作成されます。
    • テーブル ヘッダーを保持する <thead> 要素が作成されます。
    • <tbody> 内の @foreach ステートメントは、ピザの一覧を反復処理します。
      • Model プロパティは、分離コード ファイルで作成された PizzaListModel オブジェクトを参照します。
      • PizzaList プロパティは、分離コード ファイルで定義された PizzaList プロパティを参照します。
    • @foreach ステートメントが反復処理されるたびに、ピザのデータを保持する <tr> 要素が作成されます。
      • <td> 要素にピザのデータを表示するために、Razor 構文が使用されます。 この構文は、pizza 変数に格納された Pizza オブジェクトのプロパティを表示するために使用されます。
      • Price が、C# 文字列補間を使用して書式設定されます。
      • IsGlutenFree プロパティの値を "✔️" または空白のセルとして表示するために、三項式が使用されます。
      • ピザを削除するフォームが作成されます。
        • asp-page-handler 属性は、フォームを分離コード ファイル内の Delete ハンドラーに送信する必要があることを示します。 このハンドラーは、後のユニットで作成します。
        • asp-route-id 属性は、Pizza オブジェクトの Id プロパティを Delete ハンドラーに渡す必要があることを示します。
  3. ファイルを保存します。 ブラウザーで、Pizza List ページがピザの一覧で更新されます。 GitHub Codespaces を使用している場合、ファイルは自動的に保存されますが、ブラウザー タブを手動で更新する必要があります。

作業リストを含む Pizza List ページのスクリーンショット。

良くできました ピザの一覧を表示する Razor ページを作成しました。 次のユニットでは、タグ ヘルパーとページ ハンドラーについて学習します。