演習 - ルート パラメーターを使用してアプリのナビゲーションを改善する
Blazor のルート パラメーターによって、URL で渡されたデータにコンポーネントからアクセスできるようになります。 ルート パラメーターを使用すると、注文の OrderId
によって、アプリから特定の注文にアクセスできるようになります。
顧客は、特定の注文に関する詳細情報を表示できることを望んでいます。 そこで、あなたは、顧客が自分の注文に直接移動されるように、精算ページを更新することにしました。 その後、現在まだ受け取っていない注文があれば顧客が追跡できるように、注文ページを更新します。
この演習では、ルート パラメーターを使用する新しい注文詳細ページを追加します。 その後、パラメーターに制約を追加して、正しいデータ型を確認する方法を確認します。
注文詳細ページを作成する
Visual Studio Code のメニューで、[ファイル]>[新しいテキスト ファイル] を選択します。
言語として ASP.NET Razor を選択します。
このコードを使用して注文詳細ページのコンポーネントを作成します。
@page "/myorders/{orderId}" @inject NavigationManager NavigationManager @inject HttpClient HttpClient <div class="top-bar"> <a class="logo" href=""> <img src="img/logo.svg" /> </a> <NavLink href="" class="nav-tab" Match="NavLinkMatch.All"> <img src="img/pizza-slice.svg" /> <div>Get Pizza</div> </NavLink> <NavLink href="myorders" class="nav-tab"> <img src="img/bike.svg" /> <div>My Orders</div> </NavLink> </div> <div class="main"> @if (invalidOrder) { <h2>Order not found</h2> <p>We're sorry but this order no longer exists.</p> } else if (orderWithStatus == null) { <div class="track-order"> <div class="track-order-title"> <h2> <text>Loading...</text> </h2> <p class="ml-auto mb-0"> ... </p> </div> </div> } else { <div class="track-order"> <div class="track-order-title"> <h2> Order placed @orderWithStatus.Order.CreatedTime.ToLongDateString() </h2> <p class="ml-auto mb-0"> Status: <strong>@orderWithStatus.StatusText</strong> </p> </div> <div class="track-order-body"> <div class="track-order-details"> @foreach (var pizza in orderWithStatus.Order.Pizzas) { <p> <strong> @(pizza.Size)" @pizza.Special.Name (£@pizza.GetFormattedTotalPrice()) </strong> </p> } </div> </div> </div> } </div> @code { [Parameter] public int OrderId { get; set; } OrderWithStatus orderWithStatus; bool invalidOrder = false; protected override async Task OnParametersSetAsync() { try { orderWithStatus = await HttpClient.GetFromJsonAsync<OrderWithStatus>( $"{NavigationManager.BaseUri}orders/{OrderId}"); } catch (Exception ex) { invalidOrder = true; Console.Error.WriteLine(ex); } } }
このページは、MyOrders コンポーネントに似ているように見えます。 OrderController を呼び出していますが、今回は特定の注文を要求しています。
OrderId
が一致するものです。 この要求を処理するコードを追加しましょう。Ctrl+S キーを選択して、変更を保存します。
ファイル名には OrderDetail.razor を使用します。 このファイルは、Pages ディレクトリに保存するようにしてください。
エクスプローラーで、OrderController.cs を選択します。
PlaceOrder
メソッドの下に、注文を状態と一緒に返す新しいメソッドを追加します。[HttpGet("{orderId}")] public async Task<ActionResult<OrderWithStatus>> GetOrderWithStatus(int orderId) { var order = await _db.Orders .Where(o => o.OrderId == orderId) .Include(o => o.Pizzas).ThenInclude(p => p.Special) .Include(o => o.Pizzas).ThenInclude(p => p.Toppings).ThenInclude(t => t.Topping) .SingleOrDefaultAsync(); if (order == null) { return NotFound(); } return OrderWithStatus.FromOrder(order); }
このコードによって、Order コントローラーが URL に orderId を格納して HTTP 要求に応答できるようになりました。 このメソッドは次に、この ID を使用してデータベースのクエリを実行し、注文が見つかった場合は
OrderWithStatus
オブジェクトを返します。この新しいページを、顧客が精算を行うときに使用しましょう。Checkout.razor コンポーネントを更新する必要があります。
エクスプローラーで、[ページ] を展開します。 次に、Checkout.razor を選択します。
行われた注文の注文 ID を使用するように、以下の呼び出しを変更します。
NavigationManager.NavigateTo($"myorders/{newOrderId}");
既存のコードでは既に、注文の実行からの応答として
newOrderId
をキャプチャしていました。 ここでそれを利用すれば、その注文に直接移動できます。
ルート パラメーターを正しいデータ型に制限する
アプリは、(http://localhost:5000/myorders/6)
のような数値の注文 ID を持つ要求にのみ応答する必要があります。 数値以外の注文を使おうとするユーザーがいても止められません。 これを変更してみましょう。
エクスプローラーで、[ページ] を展開します。 次に、OrderDetail.razor を選択します。
コンポーネントで整数のみが受け入れられるように、ルート パラメーターを変更します。
@page "/myorders/{orderId:int}"
これで、
(http://localhost:5000/myorders/non-number)
に移動しようとした場合、Blazor のルーティングでは URL の一致が見つからず、"ページが見つかりません" が返されます。Visual Studio Code で F5 を選択します。 または [実行] メニューから [デバッグの開始] を選択します。
アプリ、注文、チェックアウトを順次移動します。注文の詳細画面に遷移し、注文の状態を確認します。
異なる注文 ID を試します。 有効な注文ではない整数を使用すると、"注文が見つかりません" というメッセージが表示されます。
整数以外の注文 ID を使用すると、"ページが見つかりません" が表示されます。 さらに重要なのは、アプリにハンドルされない例外が発生しない点です。
アプリを停止するには、Shift + F5 キーを選択します。
注文ページを更新する
この時点で、My Orders ページには詳細を表示するためのリンクがありますが、URL が間違っています。
エクスプローラーで、[ページ] を展開します。 次に、MyOrders.razor を選択します。
<a href="myorders/" class="btn btn-success">
要素を次のコードに置き換えます。<a href="myorders/@item.Order.OrderId" class="btn btn-success">
この演習のために最後のピザの注文を作成することで、このコードがどのように機能するかをテストできます。 次に [My Orders] を選択し、[Track >] リンクをたどります。