Ü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 im Menü in Visual Studio Code Datei>Neue Textdatei aus.

  2. Wählen Sie ASP.NET Razor als Sprache aus.

  3. Erstellen Sie mit diesem Code eine Komponente für eine Auftragsdetailseite:

    @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. Rufen Sie OrderController auf, aber dieses Mal für eine bestimmte Bestellung. Sie soll mit OrderId übereinstimmen. Fügen wir nun den Code hinzu, der diese Anforderung verarbeitet.

  4. Drücken Sie STRG+S, um Ihre Änderungen zu speichern.

  5. Verwenden Sie als Dateinamen OrderDetail.razor. Stellen Sie sicher, dass Sie die Datei im Verzeichnis Pages speichern.

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

  7. 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 kann der Controller Order 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.

    Verwenden Sie diese neue Seite, wenn ein Kunde zum Check-Out geht. Sie müssen die Komponente Checkout.razor aktualisieren.

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

  9. Ä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. Das ändern wir jetzt.

  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: Bildschirm „Seite nicht gefunden“.

  4. Drücken Sie in Visual Studio Code F5. Wählen Sie alternativ Debuggen starten im Menü Ausführen aus.

    Screenshot: Auftragsdetailseite für eine einzelne Bestellung.

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

  5. Probieren Sie unterschiedliche Bestell-IDs aus. Wenn Sie einen Integerwert verwenden, der keine gültige Bestellung darstellt, erhalten Sie die Meldung Bestellung nicht gefunden.

    Screenshot: Meldung „Bestellung nicht gefunden“

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

  6. Drücken Sie UMSCHALT + F5, um die App zu beenden.

Aktualisieren der Bestellseite

Derzeit enthält die Seite My Orders (Meine Bestellungen) Links, um weitere Details anzuzeigen, aber die URL ist 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 My Orders (Meine Bestellungen) aus, und folgen Sie dann dem Link Track > (Nachverfolgen).