Oefening: navigatie in uw Blazor-app wijzigen met behulp van de @page-instructie
Blazor heeft een navigatiestatushulp waarmee C#-code een URI in uw app kan beheren. Er is ook een NavLink-onderdeel dat een vervanging is voor het <a> element. Een van de functies van NavLink is het toevoegen van een actieve klasse aan HTML-koppelingen voor de menu's van een app.
Uw team heeft een begin gemaakt met de Blazing Pizza-app en blazor-onderdelen gebouwd om pizza's en bestellingen te vertegenwoordigen. De app moet nu afrekenen en andere bestellingsgerelateerde pagina's toevoegen.
In deze oefening voegt u een nieuwe betaalpagina toe, voegt u een bovenste navigatie toe aan de app en gebruikt u vervolgens een Blazor NavLink-onderdeel om uw code te verbeteren.
De bestaande app van uw team klonen
Note
Deze module maakt gebruik van de .NET-opdrachtregelinterface (CLI) en Visual Studio Code voor lokale ontwikkeling. Nadat u deze module hebt voltooid, kunt u de concepten toepassen met behulp van Visual Studio (Windows) of Visual Studio voor Mac (macOS). Gebruik Visual Studio Code voor Windows, Linux en macOS voor continue ontwikkeling.
In deze module wordt de .NET 9.0 SDK gebruikt. Zorg ervoor dat .NET 9.0 is geïnstalleerd door de volgende opdracht uit te voeren in de opdrachtterminal van uw voorkeur:
dotnet --list-sdks
Uitvoer die vergelijkbaar is met het volgende voorbeeld wordt weergegeven:
8.0.100 [C:\Program Files\dotnet\sdk]
9.0.100 [C:\Program Files\dotnet\sdk]
Zorg ervoor dat er een versie wordt vermeld die begint met 9 . Als er geen wordt vermeld of de opdracht niet wordt gevonden, installeert u de meest recente .NET 9.0 SDK.
Als u uw eerste Blazor-app maakt, volgt u de installatie-instructies voor Blazor om de juiste versie van .NET te installeren en te controleren of uw computer correct is ingesteld. Stop bij de stap 'Uw app maken'.
Open Visual Studio Code.
Open de geïntegreerde terminal vanuit Visual Studio Code door Weergave te selecteren. Selecteer Terminal in het hoofdmenu.
Ga in de terminal naar de locatie waar u het project wilt maken.
Kloon de app vanuit GitHub.
git clone https://github.com/MicrosoftDocs/mslearn-blazor-navigation.git BlazingPizzaSelecteer Bestand en selecteer Map openen.
Ga in het dialoogvenster Openen naar de map BlazingPizza en kies Map selecteren.
Visual Studio Code vraagt u mogelijk om niet-opgeloste afhankelijkheden. Selecteer Terugzetten.
Voer de app uit om te controleren of alles goed werkt.
Selecteer F5 in Visual Studio Code. Of selecteer in het menu Uitvoeren, Foutopsporing starten.
Configureer enkele pizza's en voeg ze toe aan uw bestelling. Selecteer Order > onder aan de pagina. Het standaardbericht 'Er is niets op dit adres', wordt weergegeven omdat er nog geen betaalpagina is.
Als u de app wilt stoppen, selecteert u Shift + F5.
Een betaalpagina toevoegen
Selecteer in de verkenner van Visual Studio Code App.razor.
<Router AppAssembly="@typeof(Program).Assembly" PreferExactMatches="@true"> <Found Context="routeData"> <RouteView RouteData="@routeData" /> </Found> <NotFound> <LayoutView> <p>Sorry, there's nothing at this address.</p> </LayoutView> </NotFound> </Router>Het
<NotFound>codeblok is wat klanten zien of ze proberen naar een pagina te gaan die niet bestaat.Vouw pagina's uit in de verkenner, klik met de rechtermuisknop op de map en selecteer Nieuw bestand.
Geef het nieuwe bestand Checkout.razor een naam. Schrijf in dit bestand de volgende code:
@page "/checkout" @inject OrderState OrderState @inject HttpClient HttpClient @inject NavigationManager NavigationManager <div class="top-bar"> <a class="logo" href=""> <img src="img/logo.svg" /> </a> <a href="" class="nav-tab"> <img src="img/pizza-slice.svg" /> <div>Get Pizza</div> </a> </div> <div class="main"> <div class="checkout-cols"> <div class="checkout-order-details"> <h4>Review order</h4> @foreach (var pizza in Order.Pizzas) { <p> <strong> @(pizza.Size)" @pizza.Special.Name (£@pizza.GetFormattedTotalPrice()) </strong> </p> } <p> <strong> Total price: £@Order.GetFormattedTotalPrice() </strong> </p> </div> </div> <button class="checkout-button btn btn-warning"> Place order </button> </div> @code { Order Order => OrderState.Order; }Deze pagina bouwt voort op de huidige app en maakt gebruik van de app-status die is opgeslagen in
OrderState. De eerstedivis de nieuwe koptekstnavigatie van de app. Laten we deze toevoegen aan de indexpagina.Vouw in de Verkenner Pagina's uit en selecteer index.razor.
Voeg boven de
<div class="main">klasse detop-barHTML toe.<div class="top-bar"> <a class="logo" href=""> <img src="img/logo.svg" /> </a> <a href="" class="nav-tab" > <img src="img/pizza-slice.svg" /> <div>Get Pizza</div> </a> </div>Als we op deze pagina zijn, zou het nuttig zijn om de klanten aan te tonen door de link te markeren. Het team heeft al een
activecss-klasse gemaakt, dus voegactivetoe aan hetclasskenmerk dat denav-tabstijl al bevat.<div class="top-bar"> <a class="logo" href=""> <img src="img/logo.svg" /> </a> <a href="" class="nav-tab active" > <img src="img/pizza-slice.svg" /> <div>Get Pizza</div> </a> </div>Selecteer F5 in Visual Studio Code. Of selecteer in het menu Uitvoeren, Foutopsporing starten.
De app heeft nu een mooie menubalk bovenaan, waaronder het logo van het bedrijf. Voeg een aantal pizza's toe en selecteer de knop Bestellen om naar de betaalpagina te gaan. De pizza's worden vermeld en de actieve indicator ontbreekt in het menu.
Als u de app wilt stoppen, selecteert u Shift + F5.
Klanten toestaan om een bestelling te plaatsen
Op dit moment staat de betaalpagina niet toe dat klanten hun bestellingen plaatsen. De logica van de app moet de bestelling opslaan om naar de keuken te verzenden. Nadat de bestelling is verzonden, sturen we klanten terug naar de startpagina.
Vouw Pagina's uit in de Verkenner en selecteer Checkout.razor.
Wijzig het knopelement met een aanroep naar de
PlaceOrdermethode. Voeg de@onclickendisabledkenmerken toe zoals wordt weergegeven:<button class="checkout-button btn btn-warning" @onclick="PlaceOrder" disabled=@isSubmitting> Place order </button>We willen niet dat klanten dubbele orders plaatsen, dus schakelen we de knop Bestelling plaatsen uit totdat de bestelling is verwerkt.
Voeg in het
@codeblok deze code toe onder deOrder Order => OrderState.Order;code.bool isSubmitting; async Task PlaceOrder() { isSubmitting = true; var response = await HttpClient.PostAsJsonAsync(NavigationManager.BaseUri + "orders", OrderState.Order); var newOrderId= await response.Content.ReadFromJsonAsync<int>(); OrderState.ResetOrder(); NavigationManager.NavigateTo("/"); }Met de voorgaande code wordt de knop Bestelling plaatsen uitgeschakeld, JSON gepost en toegevoegd aan pizza.db, wordt de bestelling gewist en wordt
NavigationManagergebruikt om klanten om te leiden naar de startpagina.U moet code toevoegen om de bestelling af te handelen. Voeg een OrderController-klasse toe voor deze taak. Als u naar PizzaStoreContext.cs kijkt, ziet u alleen ondersteuning voor entity framework-databases voor
PizzaSpecials. Laten we dat eerst oplossen.
Ondersteuning voor entity framework toevoegen voor bestellingen en pizza's
Selecteer PizzaStoreContext.cs in de Bestandsverkenner.
Vervang de
PizzaStoreContextklasse door deze code:public class PizzaStoreContext : DbContext { public PizzaStoreContext( DbContextOptions options) : base(options) { } public DbSet<Order> Orders { get; set; } public DbSet<Pizza> Pizzas { get; set; } public DbSet<PizzaSpecial> Specials { get; set; } public DbSet<Topping> Toppings { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); // Configuring a many-to-many special -> topping relationship that is friendly for serialization modelBuilder.Entity<PizzaTopping>().HasKey(pst => new { pst.PizzaId, pst.ToppingId }); modelBuilder.Entity<PizzaTopping>().HasOne<Pizza>().WithMany(ps => ps.Toppings); modelBuilder.Entity<PizzaTopping>().HasOne(pst => pst.Topping).WithMany(); } }Met deze code wordt ondersteuning voor entity framework toegevoegd voor de bestellings- en pizzaklassen van de app.
Selecteer in Visual Studio Code in het menu Bestand>nieuw bestand.
Voer OrderController.cs in als bestandsnaam. Zorg ervoor dat u het bestand opslaat in dezelfde map als OrderState.cs.
Voeg de volgende code toe:
using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; namespace BlazingPizza; [Route("orders")] [ApiController] public class OrdersController : Controller { private readonly PizzaStoreContext _db; public OrdersController(PizzaStoreContext db) { _db = db; } [HttpGet] public async Task<ActionResult<List<OrderWithStatus>>> GetOrders() { var orders = await _db.Orders .Include(o => o.Pizzas).ThenInclude(p => p.Special) .Include(o => o.Pizzas).ThenInclude(p => p.Toppings).ThenInclude(t => t.Topping) .OrderByDescending(o => o.CreatedTime) .ToListAsync(); return orders.Select(o => OrderWithStatus.FromOrder(o)).ToList(); } [HttpPost] public async Task<ActionResult<int>> PlaceOrder(Order order) { order.CreatedTime = DateTime.Now; // Enforce existence of Pizza.SpecialId and Topping.ToppingId // in the database - prevent the submitter from making up // new specials and toppings foreach (var pizza in order.Pizzas) { pizza.SpecialId = pizza.Special.Id; pizza.Special = null; } _db.Orders.Attach(order); await _db.SaveChangesAsync(); return order.OrderId; } }Met de voorgaande code kan onze app alle huidige orders ophalen en een bestelling plaatsen. Met
[Route("orders")]het Blazor-kenmerk kan deze klasse binnenkomende HTTP-aanvragen verwerken voor /orders en /orders/{orderId}.Sla uw wijzigingen op met Ctrl+S.
Selecteer OrderState.cs in Bestandsbeheer.
Wijzig
RemoveConfiguredPizzaonder aan de klasse onder deResetOrder()methode om de volgorde opnieuw in te stellen:public void ResetOrder() { Order = new Order(); }
De functionaliteit voor uitchecken testen
Selecteer F5 in Visual Studio Code. Of selecteer in het menu Uitvoeren, Foutopsporing starten.
De app moet worden gecompileerd, maar als u een bestelling maakt en probeert uit te checken, ziet u een runtimefout. De fout treedt op omdat onze pizza.db SQLLite-database is gemaakt voordat er ondersteuning was voor bestellingen en pizza's. We moeten het bestand verwijderen, zodat er een nieuwe database correct kan worden gemaakt.
Als u de app wilt stoppen, selecteert u Shift + F5.
Verwijder in de Verkenner het bestand pizza.db.
Selecteer F5. Of selecteer in het menu Uitvoeren, Foutopsporing starten.
Voeg als test pizza's toe, ga naar de kassa en plaats een bestelling. U wordt omgeleid naar de startpagina en u kunt zien dat de bestelling nu leeg is.
Als u de app wilt stoppen, selecteert u Shift + F5.
De app wordt verbeterd. We hebben pizzaconfiguratie en een kassa. We willen klanten toestaan om de status van hun pizzaorder te zien nadat ze deze hebben geplaatst.
Een orderspagina toevoegen
Vouw pagina's uit in de verkenner, klik met de rechtermuisknop op de map en selecteer Nieuw bestand.
Noem het nieuwe bestand MyOrders.razor. Schrijf in dit bestand de volgende code:
@page "/myorders" @inject HttpClient HttpClient @inject NavigationManager NavigationManager <div class="top-bar"> <a class="logo" href=""> <img src="img/logo.svg" /> </a> <a href="" class="nav-tab"> <img src="img/pizza-slice.svg" /> <div>Get Pizza</div> </a> <a href="myorders" class="nav-tab active"> <img src="img/bike.svg" /> <div>My Orders</div> </a> </div> <div class="main"> @if (ordersWithStatus == null) { <text>Loading...</text> } else if (!ordersWithStatus.Any()) { <h2>No orders placed</h2> <a class="btn btn-success" href="">Order some pizza</a> } else { <div class="list-group orders-list"> @foreach (var item in ordersWithStatus) { <div class="list-group-item"> <div class="col"> <h5>@item.Order.CreatedTime.ToLongDateString()</h5> Items: <strong>@item.Order.Pizzas.Count()</strong>; Total price: <strong>£@item.Order.GetFormattedTotalPrice()</strong> </div> <div class="col"> Status: <strong>@item.StatusText</strong> </div> @if (@item.StatusText != "Delivered") { <div class="col flex-grow-0"> <a href="myorders/" class="btn btn-success"> Track > </a> </div> } </div> } </div> } </div> @code { List<OrderWithStatus> ordersWithStatus = new List<OrderWithStatus>(); protected override async Task OnParametersSetAsync() { ordersWithStatus = await HttpClient.GetFromJsonAsync<List<OrderWithStatus>>( $"{NavigationManager.BaseUri}orders"); } }De navigatie moet worden gewijzigd op alle pagina's die we nu hebben om een koppeling naar de nieuwe pagina Mijn orders op te nemen. Open Checkout.razor en Index.razor en vervang de navigatie door deze code:
<div class="top-bar"> <a class="logo" href=""> <img src="img/logo.svg" /> </a> <a href="" class="nav-tab active" > <img src="img/pizza-slice.svg" /> <div>Get Pizza</div> </a> <a href="myorders" class="nav-tab" > <img src="img/bike.svg" /> <div>My orders</div> </a> </div>Met behulp van
<a>elementen kunnen we beheren welke de actieve pagina handmatig is door deactiveCSS-klasse toe te voegen. Laten we alle navigatie bijwerken om in plaats daarvan een NavLink-onderdeel te gebruiken.Gebruik op alle drie de pagina's met navigatie (Index.razor, Checkout.razor en MyOrders.razor) dezelfde Blazor-code voor navigatie:
<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>De
activecss-klasse wordt nu automatisch toegevoegd aan pagina's door het NavLink-onderdeel . U hoeft dit niet te onthouden op elke pagina waarop de navigatie is ingeschakeld.Nadat een bestelling is geplaatst, is de laatste stap het omleiden van
NavigationManagernaar demyorderspagina. In de Verkenner, vouw Pagina's uit en selecteer vervolgens Checkout.razor.Wijzig de
PlaceOrdermethode om om te leiden naar de juiste pagina door door te geven/myordersaanNavigationManager.NavigateTo():async Task PlaceOrder() { isSubmitting = true; var response = await HttpClient.PostAsJsonAsync($"{NavigationManager.BaseUri}orders", OrderState.Order); var newOrderId = await response.Content.ReadFromJsonAsync<int>(); OrderState.ResetOrder(); NavigationManager.NavigateTo("/myorders"); }Selecteer F5 in Visual Studio Code. Of selecteer in het menu Uitvoeren, Foutopsporing starten.
U moet enkele pizza's kunnen bestellen en vervolgens de bestellingen zien die momenteel in de database staan.
Stop de app door Shift + F5 te selecteren.