Alıştırma - @page yönergesini kullanarak Blazor uygulamanızda gezintiyi değiştirme
Blazor'da, C# kodunun uygulamanızdaki bir URI'nin yönetilmesine yardımcı olan bir gezinti durumu yardımcısı vardır. Ayrıca, öğesinin yerine açılan menü olan bir NavLink<a>vardır. NavLink'in özelliklerinden biri, uygulamanın menüleri için HTML bağlantılarına etkin bir sınıf eklemektir.
Takımınız Blazing Pizza uygulamasında bir başlangıç yaptı ve pizzaları ve siparişleri temsil eden Blazor bileşenleri yaptı. Şimdi uygulamanın ödeme ve siparişle ilgili diğer sayfaları eklemesi gerekiyor.
Bu alıştırmada yeni bir checkout sayfası ekleyecek, uygulamaya bir üst navigasyon ekleyecek ve ardından kodu daha iyi hale getirmek için Blazor NavLink bileşenini kullanacaksınız.
Ekibinizin mevcut uygulamasını kopyalama
Note
Bu modülde yerel geliştirme için .NET komut satırı arabirimi (CLI) ve Visual Studio Code kullanılır. Bu modülü tamamladıktan sonra Visual Studio (Windows) veya Mac için Visual Studio (macOS) kullanarak kavramları uygulayabilirsiniz. Sürekli geliştirme için Windows, Linux ve macOS için Visual Studio Code kullanın.
Bu modülde .NET 9.0 SDK kullanılır. Tercih ettiğiniz komut terminalinde aşağıdaki komutu çalıştırarak .NET 9.0'ın yüklü olduğundan emin olun:
dotnet --list-sdks
Aşağıdaki örneğe benzer bir çıkış görüntülenir:
8.0.100 [C:\Program Files\dotnet\sdk]
9.0.100 [C:\Program Files\dotnet\sdk]
ile 9 başlayan bir sürümün listelendiğinden emin olun. Hiçbiri listelenmiyorsa veya komut bulunamazsa en son .NET 9.0 SDK'sını yükleyin.
İlk Blazor uygulamanızı oluşturuyorsanız, .NET'in doğru sürümünü yüklemek ve makinenizin doğru ayarlandığından emin olmak için Blazor'ın kurulum yönergelerini izleyin. Uygulamanızı oluşturun adımında durun.
Visual Studio Code'u açın.
Visual Studio Code'dan tümleşik terminali açmak için Görünüm seçeneğini seçin. Ardından ana menüde Terminal'i seçin.
Terminalde, projenin oluşturulmasını istediğiniz yere gidin.
GitHub'dan uygulamayı kopyalayın.
git clone https://github.com/MicrosoftDocs/mslearn-blazor-navigation.git BlazingPizzaDosya'yı ve ardından Klasörü aç'ı seçin.
Aç iletişim kutusunda BlazingPizza klasörüne gidin ve Klasör Seç'i seçin.
Visual Studio Code çözümlenmemiş bağımlılıklar hakkında sizden bilgi isteyebilir. Geri Yükle'yi seçin.
Her şeyin düzgün çalıştığını denetlemek için uygulamayı çalıştırın.
Visual Studio Code'da F5'i seçin. Veya Çalıştır menüsünde Hata Ayıklamayı Başlat'ı seçin.
Bazı pizzaları yapılandırın ve siparişinize ekleyin. Sayfanın altındaki Sipariş >'i seçin. "Üzgünüz, bu adreste hiçbir şey yok" varsayılan iletisi görüntülenir çünkü henüz bir ödeme sayfası yoktur.
Uygulamayı durdurmak için Shift + F5 seçin.
Ödeme sayfası ekle
Visual Studio Code'da, dosya gezgininde App.razor'ı seçin.
<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>Kod
<NotFound>bloğu, müşterilerin var olmayan bir sayfaya gitmeye çalıştıkları zaman gördükleridir.Dosya gezgininde Sayfalar'ı genişletin, klasöre sağ tıklayın ve Yeni Dosya'yı seçin.
Yeni dosyaya Checkout.razor adını verin. Bu dosyaya aşağıdaki kodu yazın:
@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; }Bu sayfa, geçerli uygulama üzerine kuruludur ve
OrderStateiçinde kaydedilen uygulama durumunu kullanır. İlkidiv, uygulamanın yeni başlık gezintisidir. Şimdi dizin sayfasına ekleyelim.Dosya gezgininde Sayfalar'ı genişletin ve index.razor dosyasını seçin.
<div class="main">sınıfının üstüne html'yitop-barekleyin.<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>Bu sayfadayken, bağlantıyı vurgulayarak müşterilere göstermek güzel olacaktır. Ekip zaten bir
activecss sınıfı oluşturdu, bu nedenleactive'iclassstilini zaten içerennav-tabözniteliğine ekleyin.<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>Visual Studio Code'da F5'i seçin. Veya Çalıştır menüsünde Hata Ayıklamayı Başlat'ı seçin.
Uygulamanın üst kısmında artık şirketin logosunu içeren güzel bir menü çubuğu var. Bazı pizzalar ekleyin ve ödeme sayfasına ilerlemek için Sipariş et düğmesini seçin. Menüde pizzaların listelendiğini ve etkin göstergenin eksik olduğunu görürsünüz.
Uygulamayı durdurmak için Shift + F5 seçin.
Müşterilerin sipariş vermesine izin verme
Şu anda, ödeme sayfası müşterilerin siparişlerini vermesine izin vermiyor. Uygulamanın mantığının mutfağa göndermek için siparişi depolaması gerekir. Sipariş gönderildikten sonra müşterileri giriş sayfasına geri yönlendirelim.
Dosya gezgininde Sayfalar'ı genişletin ve Checkout.razor dosyasını seçin.
düğme öğesini yöntemine
PlaceOrderyapılan bir çağrıyla değiştirin.@onclickvedisabledözniteliklerini gösterildiği gibi ekleyin:<button class="checkout-button btn btn-warning" @onclick="PlaceOrder" disabled=@isSubmitting> Place order </button>Müşterilerin yinelenen siparişler vermelerini istemiyoruz, bu nedenle sipariş işlenene kadar Sipariş ver düğmesini devre dışı bırakıyoruz.
@codebloğunda, bu koduOrder Order => OrderState.Order;kodunun altına ekleyin.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("/"); }Yukarıdaki kod, Sipariş ver düğmesini devre dışı bırakır, JSON'u gönderir ve pizza.db'ye ekler, siparişi temizler ve müşterileri ana sayfaya yönlendirmek için kullanır.
Siparişi işlemek için kod eklemeniz gerekir. Bu görev için bir OrderController sınıfı ekleyin. PizzaStoreContext.cs dosyasına bakarsanız, yalnızca Entity Framework için veritabanı desteğini görürsünüz. Önce bunu düzeltelim.
Siparişler ve pizzalar için Entity Framework desteği ekleme
Dosya gezgininde PizzaStoreContext.cs'ı seçin.
sınıfını
PizzaStoreContextşu kodla değiştirin: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(); } }Bu kod, uygulamanın siparişi ve pizza sınıfları için varlık çerçevesi desteği ekler.
Visual Studio Code'daki menüdeDosya Yeni Dosya'yı>.
Dosya adı olarak OrderController.cs girin. Dosyayı OrderState.cs ile aynı dizine kaydettiğinizden emin olun.
Aşağıdaki kodu ekleyin:
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; } }Yukarıdaki kod, uygulamamızın tüm geçerli siparişleri almasına ve sipariş vermesine olanak tanır.
[Route("orders")]Blazor özniteliği, bu sınıfın /orders ve /orders/{orderId} için gelen HTTP isteklerini işlemesini sağlar.Değişikliklerinizi Ctrl+S ile kaydedin.
Dosya gezgininde OrderState.cs'ı seçin.
RemoveConfiguredPizzayönteminin en altında,ResetOrder()'i sıralamayı sıfırlamak için değiştirin.public void ResetOrder() { Order = new Order(); }
Ödeme işlevini test edin
Visual Studio Code'da F5'i seçin. Veya Çalıştır menüsünde Hata Ayıklamayı Başlat'ı seçin.
Uygulama derlenmelidir, ancak bir sipariş oluşturup kullanıma almayı denerseniz bir çalışma zamanı hatası görürsünüz. Hatanın nedeni, pizza.db SQLLite veritabanımızın siparişler ve pizzalar için destek olmadan önce oluşturulmasıdır. Yeni bir veritabanının doğru oluşturulabilmesi için dosyayı silmemiz gerekiyor.
Uygulamayı durdurmak için Shift + F5 seçin.
Dosya gezgininde pizza.db dosyasını silin.
F5'i seçin. Veya Çalıştır menüsünde Hata Ayıklamayı Başlat'ı seçin.
Test olarak pizza ekleyin, ödeme sayfasına gidin ve sipariş ver. Giriş sayfasına yönlendirilirsiniz ve siparişin artık boş olduğunu görebilirsiniz.
Uygulamayı durdurmak için Shift + F5 seçin.
Uygulama geliştiriliyor. Pizza düzenlememiz ve ödeme işlemimiz var. Müşterilerin pizza siparişlerini verdikten sonra siparişlerinin durumunu görmelerine izin vermek istiyoruz.
Siparişler sayfası ekleme
Dosya gezgininde Sayfalar'ı genişletin, klasöre sağ tıklayın ve Yeni Dosya'yı seçin.
Yeni dosyayı MyOrders.razor olarak adlandırın. Bu dosyaya aşağıdaki kodu yazın:
@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"); } }Yeni Siparişlerim sayfasının bağlantısını eklemek için gezintinin şu anda sahip olduğumuz tüm sayfalarda değişmesi gerekir. Checkout.razor ve Index.razor dosyasını açın ve gezintiyi şu kodla değiştirin:
<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><a>öğelerini kullanarak,activecss sınıfını ekleyerek hangi sayfanın etkin olduğunu elle yönetebiliriz. Haydi tüm gezintiyi NavLink bileşenini kullanacak şekilde güncelleyelim.Gezinti içeren sayfaların üçünde (Index.razor, Checkout.razor ve MyOrders.razor), gezinti için aynı Blazor kodunu kullanın:
<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>activeCss sınıfı artık NavLink bileşeni tarafından sayfalara otomatik olarak eklenir. Her sayfada, gezinme açık olduğunda bunu yapmayı hatırlamanıza gerek yok.Son adım, sipariş verildikten sonra
NavigationManager'ümyorderssayfasına yönlendirmek için değiştirmektir. Dosya gezgininde Sayfalar'ı genişletin ve ardından Checkout.razor öğesini seçin.Doğru sayfaya yeniden yönlendirmek için
PlaceOrderyöntemini/myordersöğesindeNavigationManager.NavigateTo()öğesini geçirerek değiştirin.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"); }Visual Studio Code'da F5'i seçin. Veya Çalıştır menüsünde Hata Ayıklamayı Başlat'ı seçin.
Bazı pizzalar sipariş edebilmeniz ve ardından şu anda veritabanındaki siparişleri görebilmeniz gerekir.
Uygulamayı durdurmak için Shift + F5 tuşlarına basın.