Übung: Verwenden von Routenparametern zur Verbesserung der Navigation Ihrer App

Abgeschlossen

Mit Blazor-Routenparametern können Komponenten auf Daten zugreifen, die in der URL übergeben werden. Routenparameter ermöglichen unserer App den Zugriff auf bestimmte Bestellungen nach deren OrderId.

Kunden möchten weitere Informationen zu bestimmten Bestellungen anzeigen. Sie entscheiden sich dazu die Check-Out-Seite zu aktualisieren, um Kunden direkt zu ihren aufgegebenen Bestellungen weiterzuleiten. Anschließend wollen Sie die Bestellseite aktualisieren, damit sie alle aktuell offenen Bestellungen nachverfolgen können.

In dieser Übung fügen Sie eine neue Seite mit Auftragsdetails hinzu, die Routenparameter verwendet. Dann erfahren Sie, wie Sie dem Parameter eine Einschränkung hinzufügen können, um den richtigen Datentyp zu überprüfen.

Erstellen einer Auftragsdetailseite

  1. Wählen Sie in Visual Studio Code im Menü "Neue Datei"> aus.

  2. Benennen Sie die neue Datei OrderDetail.razor , und speichern Sie sie im Verzeichnis "Pages ".

  3. Erstellen Sie in der neuen Datei eine Auftragsdetailseitekomponente mit diesem Code:

    @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);
          }
        }
    }
    
    

    Diese Seite ähnelt der MyOrders-Komponente . Wir rufen den OrderController auf, aber dieses Mal fordern wir eine bestimmte Bestellung an. Sie soll mit OrderId übereinstimmen. Fügen wir nun den Code hinzu, der diese Anforderung verarbeitet.

  4. Speichern Sie Ihre Änderungen, indem Sie STRG+S auswählen.

  5. Wählen Sie im Datei-Explorer OrderController.cs aus.

  6. Fügen Sie unter der PlaceOrder-Methode eine neue Methode hinzu, um Bestellungen mit einem Status zurückzugeben.

    [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);
    }
    

    Mit diesem Code konnte der Order-Controller auf eine HTTP-Anforderung mit orderId in der URL antworten. Die Methode verwendet dann diese ID, um die Datenbank abzufragen, und gibt ein OrderWithStatus-Objekt zurück, wenn eine Bestellung gefunden wird.

    Lassen Sie uns diese neue Seite verwenden, wenn ein Kunde auscheckt. Sie müssen die Checkout.razor-Komponente aktualisieren.

  7. Erweitern Sie im Datei-Explorer den Ordner Pages. Wählen Sie dann Checkout.razor aus.

  8. Ändern Sie den Aufruf des folgenden Elements so, dass die ID der aufgegebenen Bestellung verwendet wird.

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

    Der vorhandene Code hat bereits newOrderId als Antwort auf das Aufgeben der Bestellung erfasst. Sie können diese Angabe jetzt verwenden, um direkt zu dieser Bestellung zu wechseln.

Einschränken des Routenparameters auf den richtigen Datentyp

Die App sollte nur auf Anforderungen mit numerischen Bestell-IDs reagieren, z. B. (http://localhost:5000/myorders/6). Benutzer*innen werden nicht daran gehindert, nicht numerische Bestellungen zu verwenden. Ändern wir das.

  1. Erweitern Sie im Datei-Explorer den Ordner Pages. Wählen Sie dann "OrderDetail.razor" aus.

  2. Ändern Sie den Routenparameter so, dass die Komponente nur ganze Zahlen akzeptiert.

    @page "/myorders/{orderId:int}"
    
  3. Wenn nun ein Benutzer versucht, zu (http://localhost:5000/myorders/non-number) zu wechseln, findet das Blazor-Routing keine Übereinstimmung für die URL und gibt die Meldung „Seite nicht gefunden“ zurück.

    Screenshot des Bildschirms

  4. Wählen Sie in Visual Studio Code F5 aus. Oder wählen Sie im Menü "Ausführen " die Option "Debuggen starten" aus.

    Screenshot der Bestelldetailseite für eine einzelne Bestellung.

    Durchlaufen Sie die App, die Bestellung und die Check-Out-Funktion. Sie gelangen zum Bildschirm mit den Details der Bestellung und sehen den Status der Bestellung.

  5. Öffnen Sie ein neues Browserfenster, und geben Sie ein (http://localhost:5000/myorders/2). Probieren Sie unterschiedliche Bestell-IDs einschließlich Nicht-Integers aus. Wenn Sie eine ganze Zahl verwenden, die keine gültige Reihenfolge ist, wird eine Meldung "Auftrag nicht gefunden" angezeigt.

    Screenshot mit der Meldung

    Wenn Sie nicht ganzzahlige Bestell-IDs verwenden, wird die Seite nicht gefunden. Wichtiger noch: Die App zeigt keinen Ausnahmefehler an.

  6. Um die App zu beenden, wählen Sie Shift + F5.

Aktualisieren der Bestellseite

Derzeit verfügt die Seite "Meine Bestellungen " über Links, um weitere Details anzuzeigen, die URL ist jedoch falsch.

  1. Erweitern Sie im Datei-Explorer den Ordner Pages. Wählen Sie dann MyOrders.razor aus.

  2. Ersetzen Sie das <a href="myorders/" class="btn btn-success">-Element durch den folgenden Code:

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

Sie können die Funktionsweise des Codes testen, indem Sie Ihre letzte Pizzabestellung für diese Übung aufgeben. Wählen Sie dann "Meine Bestellungen" aus, und folgen Sie dem Link " Nachverfolgen > ".