练习 - 使用路由参数改进应用导航
Blazor 路由参数允许组件访问在 URL 中传递的数据。 路由参数允许我们的应用按订单的 OrderId
访问特定订单。
客户希望能够看到有关特定订单详细信息。 因此你决定更新结帐页,使客户直接转到其已下达的订单。 然后,你希望更新订单页,让用户可以跟踪任何当前未处理的订单。
在此练习中,你将添加一个利用路由参数的新订单详情页。 然后,你将了解如何向参数添加约束以检查正确的数据类型。
创建订单详情页
在 Visual Studio Code 的菜单上,选择“文件”>“新建文本文件”。
选择 ASP.NET Razor 作为语言。
使用此代码创建订单详情页组件:
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
方法下,添加新方法以返回有状态的订单。razor[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。
razorNavigationManager.NavigateTo($"myorders/{newOrderId}");
现有代码已捕获
newOrderId
作为对下订单的响应。 现在可以使用它直接转到该订单。
将路由参数限制为正确的数据类型
应用应仅响应具有数字订单 ID 的请求,例如 (http://localhost:5000/myorders/6)
。 如果有人尝试使用非数字订单,不会阻止这种行为。 让我们改变这点。
在文件资源管理器中,展开“页面”。 然后选择“OrderDetail.razor”。
更改路由参数,使组件仅接受整数。
razor@page "/myorders/{orderId:int}"
现在,如果有人尝试转到
(http://localhost:5000/myorders/non-number)
,Blazor 路由将不会查找 URL 的匹配项,并返回“未找到页面”。在 Visual Studio Code 中,选择 F5。 在“运行”菜单上,选择“开始调试”。
浏览应用,下订单并结帐。将转到订单详情屏幕,你可以在这里看到订单的状态。
尝试不同的订单 ID。 如果使用不是有效订单号的整数,将显示“未找到订单”消息。
如果使用非整数订单 ID,将显示“未找到页面”。 更重要的是,应用不会有未经处理的异常。
若要停止应用,请选择 Shift + F5。
更新订单页
目前,“我的订单”页包含查看更多详细信息的链接,但 URL 错误。
在文件资源管理器中,展开“页面”。 然后选择“MyOrders.razor”。
将
<a href="myorders/" class="btn btn-success">
元素替换为以下代码:razor<a href="myorders/@item.Order.OrderId" class="btn btn-success">
可以在此练习中下达最后一份披萨订单,测试代码的运行情况。 然后选择“我的订单”,并打开“跟踪 >”链接。