연습 - 경로 매개 변수를 사용하여 앱의 탐색 개선

완료됨

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 요청에 응답할 수 있었습니다. 그런 다음 메서드는 이 ID를 사용하여 데이터베이스를 쿼리하고, 주문이 발견되면 OrderWithStatus 개체를 반환합니다.

    고객이 체크 아웃할 때 이 새 페이지를 사용해 보겠습니다. Checkout.razor 구성 요소를 업데이트해야 합니다.

  8. 파일 탐색기에서 페이지를 확장합니다. 그런 다음, Checkout.razor를 선택합니다.

  9. 제출된 주문의 주문 ID를 사용하도록 다음에 대한 호출을 변경합니다.

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

    기존 코드는 이미 newOrderId를 주문 제출의 응답으로 캡처하고 있었습니다. 이제 이 주문을 사용하여 해당 주문으로 직접 이동할 수 있습니다.

경로 매개 변수를 올바른 데이터 형식으로 제한

앱은 (http://localhost:5000/myorders/6) 등의 숫자 순서 ID가 있는 요청에만 응답해야 합니다. 숫자가 아닌 주문을 사용하려고 하는 사용자를 차단하는 것은 없습니다. 이제 변경해 보겠습니다.

  1. 파일 탐색기에서 페이지를 확장합니다. 그런 다음, OrderDetail.razor를 선택합니다.

  2. 구성 요소가 정수만 허용하도록 경로 매개 변수를 변경합니다.

    @page "/myorders/{orderId:int}"
    
  3. 이제 누군가가 (http://localhost:5000/myorders/non-number)로 이동하려고 하면 Blazor 라우팅에서는 URL과 일치하는 항목을 찾아서 페이지를 찾을 수 없음을 반환하지 않습니다.

    페이지를 찾을 수 없음 화면의 스크린샷.

  4. Visual Studio Code에서 F5 키를 선택합니다. 또는 실행 메뉴에서 디버깅 시작을 선택합니다.

    단일 주문에 대한 주문 세부 정보 페이지를 보여주는 스크린샷.

    앱, 주문 및 체크 아웃을 진행합니다. 자세한 주문 화면으로 이동되면 주문 상태를 확인합니다.

  5. 다른 주문 ID를 사용해 보세요. 유효한 주문이 아닌 정수를 사용하는 경우 주문을 찾을 수 없음 메시지가 표시됩니다.

    주문을 찾을 수 없음 메시지를 보여 주는 스크린샷

    정수가 아닌 주문 ID를 사용하는 경우 페이지를 찾을 수 없음이 표시됩니다. 더 중요한 것은 앱에는 처리되지 않은 예외가 없다는 것입니다.

  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">
    

이 연습의 마지막 피자 주문을 만들어 어떻게 작동하는지 테스트할 수 있습니다. 그런 다음, 내 주문을 선택하고 추적 > 링크를 따라갑니다.