練習 - 使用路由參數來改善您的應用程式瀏覽

已完成

Blazor 路由參數可讓元件存取在 URL 中傳遞的資料。 路由參數允許我們的應用程式透過其 OrderId 來存取特定訂單。

客戶想要能夠查看特定訂單的詳細資訊。 因此,您決定更新結帳頁面以將客戶直接帶到他們所下的訂單。 然後,您要更新訂單頁面,以允許他們追蹤任何目前未結案的訂單。

在本練習中,您會新增使用路由參數的新訂單詳細資料頁面。 然後,您會了解如何將條件約束新增至此參數,以檢查正確的資料類型。

建立訂單詳細資料頁面

  1. 在 Visual Studio Code 的功能表中,依序選取 [檔案]> [新增文字檔]

  2. 選取 ASP.NET Razor 作為語言。

  3. 使用此程式碼建立訂單詳細資料頁面元件:

    @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 的訂單。 讓我們新增處理此要求的程式碼。

  4. 選取 Ctrl+S 來儲存您的變更。

  5. 針對檔案名稱,使用 OrderDetail.razor。 務必將檔案儲存在 Pages 目錄中。

  6. 在檔案總管中,選取 OrderController.cs

  7. 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 要求。 此方法接著使用此識別碼來查詢資料庫,如果找到訂單,則傳回 OrderWithStatus 物件。

    當客戶結帳時,讓我們使用此新頁面。您必須更新 Checkout.razor 元件。

  8. 在檔案總管中,展開 [頁面]。 然後選取 Checkout.razor

  9. 變更對下列項目的呼叫,以使用所下訂單的訂單識別碼。

    NavigationManager.NavigateTo($"myorders/{newOrderId}");
    

    現有的程式碼已經擷取 newOrderId 作為下單的回應。 您現在可以直接使用其前往該訂單。

將路由參數限制為正確的資料類型

應用程式只能使用數值訂單識別碼 (例如 (http://localhost:5000/myorders/6)) 來回應要求。 系統不會阻止某人嘗試使用非數值的訂單。 讓我們改變這點。

  1. 在檔案總管中,展開 [頁面]。 然後選取 OrderDetail.razor

  2. 變更路由參數,以便元件只接受整數。

    @page "/myorders/{orderId:int}"
    
  3. 現在,如果有人嘗試前往 (http://localhost:5000/myorders/non-number),則 Blazor 路由會找不到該 URL 的相符項,並傳回未找到的頁面。

    找不到頁面的螢幕擷取畫面。

  4. 在 Visual Studio Code 中,選取 F5。 或在 [執行] 功能表上,選取 [開始偵錯]

    顯示單一訂單詳細資料順序頁面的螢幕擷取畫面。

    瀏覽應用程式、訂購並結帳。您會被帶到詳細的訂單畫面,您可以查看訂單的狀態。

  5. 嘗試不同的訂單識別碼。 如果您使用的整數不是有效的訂單,您會收到未找到訂單的訊息。

    顯示 [找不到訂單] 訊息的螢幕擷取畫面。

    如果您使用非整數的訂單識別碼,您會看到找不到頁面。 更重要的是,該應用程式沒有未處理的例外狀況。

  6. 若要停止該應用程式,請選取 Shift + F5

更新訂單頁面

目前,[我的訂單] 頁面有連結可檢視更多詳細資料,但 URL 錯誤。

  1. 在檔案總管中,展開 [頁面]。 然後選取 MyOrders.razor

  2. 使用此程式碼取代 <a href="myorders/" class="btn btn-success"> 元素:

    <a href="myorders/@item.Order.OrderId" class="btn btn-success">
    

您可以透過為本練習製作最後一份披薩訂單來測試此程式碼的運作方式。 然後選取 [我的訂單],並遵循追蹤 > 連結。