A’dan Z’ye Blazor Öğreniyorum…
Herkese merhaba
Bu makalemde sizler ile bir önceki yazımın devam niteliği olan Blazor
teknolojisini kurmayı ve kurulum esnasında bize sabit gelen şablonu inceleyeceğiz ve bu yazımızı tamamlayacağım. Eğer yazıma gerekli ilgi oluşursa Blazor
serimin devamını yazmayı düşünüyorum. Bu yazıyı tamamladığınızda umarım herkes için güzel bir giriş seviyesinde yazı olmasını ümit ediyorum. Lafı fazla uzatmadan başlayalım.
Bu arada yazımı beğenmeyi ve paylaşmayı, bi de beni takip etmeyi unutmayın :)
Microsoft .NET Core altyapısı ile backend dünyasına oldukça kaliteli ve sürdürülebilir bir ortam sundu. Frontend tarafına ise Blazor
ile profesyonel bir yaklaşım getirdi.
Microsoft .NET Core altyapısı ile backend dünyasına oldukça kaliteli ve sürdürülebilir bir ortam sundu. Frontend tarafına ise Blazor
ile profesyonel bir yaklaşım getirdi.
- Visual Studio Kurulumu
Blazor Server uygulamaları oluşturmak için ASP.NET ve web geliştirme ile Visual Studio 2019'un en son sürümünü yüklüyoruz.
2. Blazor WebAssembly Kurulumu (.NET Core CLI ‘da Çalıştırıyoruz)
dotnet new -i Microsoft.AspNetCore.Components.WebAssembly.Templates::3.2.0-preview5.20216.8
Yükleme işlemini Tools/NuGet Package Manager/Package Manager Console
ile gerçekleştirebiliriz.
Package Manager Console ile WebAssembly yüklemesi
Yukarıda yapılan işlemlerin daha güncel halini blazor'un
kendi web sitesindenden erişebilirsiniz. Yükleme işlemlerini tamamladığımıza göre şimdi blazor’ı öğrenmek için temelden başlayalım.
Create a new project
deyip yeni bir proje oluşturuyoruz. Arama çubuğunda Blazor
diye arama yapıyor ardından Blazor App
seçeneğini seçiyoruz ve Next
diyoruz.
Şimdi projemize bir isim veriyoruz. BlazorLearn
C# isimlendirme standartlarına dikkat etmeliyiz yani kelimelerin ilk harflerini büyük kullanıyoruz. Create
dediğimizde projeyi oluşturacak.
Create
dediğimizde bize bir soru ile karşılık verecek. WebAssembly App
mi üretmek istiyorsun, Server App
mi üretmek istiyorsun.
- Server App
bizim için olayın serverda gerçekleştiğidir yani olay server side(sunucu tarafı) bir uygulama gibi düşünebiliriz. Bir server’da istekler yapıldığında o client için html render ediliyor ve client’a veriliyor. Bu işlemi ASP.NET gibi düşünebiliriz. - WebAssembly App
ise aslında bizim için SPA(Single Page Application)lara
benziyor. Yani modern Angular, React
nasıl çalışıyorsa Blazor WebAssembly
olarak çalıştığımızda aynı mantık ile çalışıyor.
Konular hemen hemen aynıdır. Sadece çalıştırma ortamına yönelik configuration ve bir takım değişiklikler dışında birini yapmamız arasında fark yoktur. Ardında Create
ile devam ediyoruz. İlk projemizi bir şablon ile birlikte oluşturuyor.
Projemizi oluşturduktan sonra aşağıdaki Şekil 6
görselinde projeye ait dosyalar görünmektedir. Eğer daha önce bir .NET Core
uygulaması geliştirdiyseniz Program.cs
dosyası yabancı gelmeyecektir. Bu dosya bizim için Configuration
dosyasıdır.
Aslında bizim geliştirme ortamımız razor
dediğimiz ortamdır. Bu ortam microsoft tarafından ilk olarak ASP.NET MVC
ile kullanmaya başladık. Aslında bu html
içerisinde C#
dilini kullanarak hızlıca html üretmemizi sağlayan bir ortamdır. Daha önce sadece MVC ’de yani backend
‘de çalışabiliyorken, şuanda Blazor ile beraber razor’ ı tamamen client side
‘dada kullanabiliyoruz.
- Razor’daki
C#'ın
olayı ortaya çıkacakHTML'i
dinamikleştirmek veHTML'e
destek verecek'Code'
için kullanmamızı sağlamasıdır. Tamamıyla göresellikle ilgi kısımdarazor'dan
yararlanıyoruz.
Bir şablon olarak gelen uygulamamız çalıştıralım ve sonucu görelim. F5
veya IIS Ecpress
çalıştırabiliriz.
Şimdi projemizi inceleyelim. Solda bir menu ve üstte bir navigation var aslında bu bizim layout’umuz.
Yukarıdaki @page
bizim için bir routing
görevi görüyor. Blazorda biz routing işlemini sayfanın başında yapıyoruz. Angular
gibi bir app-routing.ts
için de tanımlama yapmamıza gerek yoktur.
Tekrar Index.razor
sayfamıza dönersek HTML
kodunun hemen aldında SurveyPrompt
gibi bir şey görüyoruz. O da bize Şekil 11'deki
turuncu dikdörtgen içine olarak alınmış alanı çıkarıyor. Dikkat edersek böyle bir şey yok, tam olarak bunada Component
deniliyor. Burada Component
mimarisi denilen bir olay vardır. Bunun gibi benzer yapılar Angular, React
gibi yapılardada vardır. Yani bunları içi içe kullanabiliriz. Yani component bileşen demek, burada reusability(tekrar tekrar kullanılabilirlik)
vardır.
Yukarıda bahsetmiş olduğumuz component'i
inceeleyelim. Bu component shared(paylaşılan)'ın
altında burada olmasının temel amacı bunu birden fazla sayfada kullanileceğimiz componentleri
bu klasör içinde barındırırız. Şimdi SurveyPrompt.razor
componentimizi inceleyelim.
İlk önce standart html elemanlarını görüyoruz. Aslında bizi ilgilendiren teml bölüm @code {}
bölümüdür. Bunun içersinde property'ler, metodlar vb.
olabiliyor. Buda bizim iç içe component yapısı ile konuşacağımız temel bir sayfadır. Bu sayfayı temel olarak inceledikten sonra şimdi Counter.razor
componentimizi inceleyelim.
Öncelikle @page
ile başlıyor, bu bize bir routing işlemi olduğunu söylemektedir. Ardından basit bir html
ile devam etmektedir. Html
içerisinde @currentCount
değerini görüyoruz. @
ben şimdi razor yazıyorum demek diye ifade edebiliriz. “ Değişken değerlerini HTML tarafında @ operatörü ile kolayca kullanabiliriz.” @currentCount
bizim @code{ }
blogumuzun içerisindeki bir değişkendir. @code
blogunun currentCount
değeri burada 0
olarak görünüyor ve yine anı blog içinde IncrementCount()
metodu ilede currentCount
değişkenini bir bir arttırıyoruz. Bu metod buttonun@onclik
event’i tetiklendiğinde çalışmaktadır. Şimdi iknci metodumuzu yazalım. İlk metot ile currentCount
değerini bir bir arttırıyoruz. İkinci metot ike bu değeri ikişer ikişer arttırma işlemini yapıyoruz. Bu örnekleri yapmamızdaki temel amaç bunlara aşina olmamızdır.
Index.razor
ve Counter.razor
componentlerimizi inceledikten sonra şimdi FetchData.razor
componentimizi inceleyip, öncelikle bu component’i açıyoruz.
Böyle durumlarda ilk başta @code{ }
bölümünü incelememiz bizim için sağlıklı olacaktır. @code
içinde nelerin olduğuna bir göz atmamız her zaman en iyisidir. Aslında baktığımızda @code
blogu bizim içerisinde C#
yapılarını oluşturacağımız bir yerdir. Burada bir array, bir metot ve bir class oluşturulmuştur. Yani bir çok C#
yapısını blog içerisinde oluşturacağımız bir yer.
Bizim bir object(nesne)
class’ımız mevcuttur. Bu class bizim apimizin
modelini bize vermektedir. Şöyle anlatmak gerekirse API
ile bize dönecek değerin parametrelerini column değerlerini bir object(nesne)
olarak yapmamıza olanak tanır. Date, TemperatureC, Summary ve TemperatureF
olarak column değerlerini alır. TemperatureF C# 6.0
ile gelişmiş bir özellik bu özelliği direk buradan okuruz.
@Code
bölümünü incelemeye devam ettiğimizde OnInitializedAsync()
metodumuz ile karşılaşırız. Bu metot sayfa yüklendiği anda çalışacak metodumuzdur. OnInitializedAsync()
adında hazır bir event’ımız var. Dikkat edersek biz bunu override
edebiliyoruz. Bu metot sayfa açıldığı zaman çalışacağına göre forecast’ı
hemen metot içinde Http.GetJsonAsync
ile newliyoruz. Bu bizim herhangi bir API'ye
istek yapabilmemizi sağlıyor. Burada bir dosyaya yapmış, biz bunu çok farklı bir noktayada yapabiliriz. sample-data/weather.json
yerine API
adresini yazmamız ve bize json
dönmesi yeterlidir. Eğer dönüş tipide kullanılırsa çok güzel olur. Örnek vermek gerekirse WeatherForecast[]
bizim json’ımızı bu array’e çeviriyor. Bu noktada artık elimizde bir forecast
mevcuttur.
Şimdilik @code
bölümünü incelemeyi bitirdiğimize göre sayfanın başına çıkıp incelemeye devam edelim.
Sayfanın en başında @page
ile daha önce bahsettiğimiz gibi routing işlemlerini gerçekleştiriyoruz. Ardından @inject
diye bir şey görüyoruz, bu bize dependency injection olduğunu söylüyor. Eğer bir component’te inject
görüyorsak bağımlılığı bağladığımızı anlamalıyız. Demekki HttpClient
bir service onun bir somut sınıfını oluşturmamızı sağlıyor. Onudan Http
ismi ile kullanmamıza olanak sağlıyor, buraya istediğimiz ismi verebiliriz.
Ardından standart html kodları ile devam ediyor. Ardından razor
çalıştırıyor. Bu şartlı blog gösterme olayıdır. Yani eğer forecast
null ise o zaman Loading… yazmamızı söylüyor ama null değilse o zaman bir tablo oluştur. Bunun içinde herbir hava tahmini için bir @foreach
yapıyor ve burada herbir hava tahminini listeliyoruz. Burada C#
bilgimiz ile yapabildiğimiz tüm işlemleri gerçekleştirebiliriz bu tamamem bizim C#
bilgimize bağlıdır.
EKSİKLİKLER
Değişiklik yapıldığı zaman, hızlıca tekrar derleme işleminin yapılıp sonuçlarının görülememesi, bunun için uygulamanın durdurulup yeniden derlenmesinin gereksinimi ve debug işlemlerinin henüz eklenmemesi, ilk göze çarpan eksikler olarak görülebilir. Ama bunlar aşılamayacak sorunlar değildir. Server Side kodların ClientSide tarafında, browserların gücü kullanılarak derleme işleminin yapılması, sayfadaki değişkenlerin Html nesnelere @bind edilerek basılması ve ilgili nesnelerin propertylerinin değişmesi durumunda, sayfanın (SPA) tekrar render edilerek değişimin direk görülmesi gerçekten muazzam. Unutulmamalıdır ki Blazor halen deneysel olarak geliştirilen bir .NET web frameworküdür. Ve bence WebAssembly web teknolojilerinin gelecekteki en büyük gücüdür. Çünkü browser istenen her dili derlemektedir. Bu da Javascript’e büyük bir destek sağlamakta ve front tarafı da dilden bağımsız bir hale getirmektedir.
Aslında yazım bu bölümde bitiyor, fakat tüm dosyalarımızı inceleyemekdik. Bundan dolayı dosyalarımızı biraz daha detaylı olarak tanımlamak istiyorum…
Blazor’da Esas Bileşenler :
- Layouts
- Routing
- Dependency injection
- Lazy loading
- Unit testing harness
Routing
App.razor : sayfası üzerinde tanımlanır. Başlangıç dosyası olarak “Program.cs” dosyası gösterilmiştir.
Program.cs : console uygulamasında olduğu gibi, klasik bir Main()
methodu ile yaşam döngüsüne başlanmaktadır. “Index” sayfasında
kullanılacak “app” tagı ile render edileceği belirtilmiştir. Ayrıca diğer tüm kullanılacak servis tanımları burada yapılır.
Wwwroot/index.html : Program.cs’de geçen “app” başlangıç sayfası
olan “index.html” de kullanılır. Bu sayfada, proje içerisinde kullanılan “bootstrap” ve” blazor-boot” dosyaları include edilmesinden başka <app>Loading…</app> ile render edilecek sayfa “<body>” içerisine konur.
Imports.razor : Tüm sayfalarda kullanılacak .Net ve diğer kütüphaneler burada tanımlanır.
Layouts
Shared/MainLayout.razor : Sayfanın bir başka Interface veya
sayfadan türetilmesi ==> Blazor syntax =>
“@inherits LayoutComponentBase” şeklinde yapılır. Sayfada kullanılacak Menu ==> “<NavMenu />” şeklinde, ana kısım “@Body” tagı ile belirlenir.
Shared/NavMenu.razor : Sayfanın solundaki menu olarak tanımlanmıştır “<NavLink” ==> “/” tıklanınca herbir sayfada tanımlanan path’e gidilir. Bu şekilde bir tanımlama ==> “/” ana sayfa demektir. “/counter” Counter sayfasına git demektir. İlgili Router tanımlaması yine “counter” sayfası üzerinde belirtilmektedir. Kısaca erişilecek sayfanın fiziksel adı üzerine yazılır. Erişilmek istenen adres bu ve buna benzer şekilde tanımlanır.
Shared/SurveyPropmt.razor : userControl olarak index sayfasında
kullanılan bu sayfa aşağıda görüldüğü gibi “@code{}” içerisine
ilgili “Title” property’si tanımlanmıştır. Sayfa üzerinde parametre olarak girilen “@Title” değişkeni bir text ve tıklandığında gidilecek bir link bulunmaktadır.
Pages/Index.razor : @page “/” ile sayfaya erişim şekli tanımlanmıştır. “<SurveyPrompt Title=”How is Blazor working for you?” />” Başka bir yerde tanımlı bir UserControl yani başka bir sayfadır. Property’si de Title’dır. Bence bu da efsane bir kullanım. Angulardaki Directivelere denk gelmektedir.
Pages/Counter.razor : NavMenu’de “/counter” şeklinde tanımlı bir sayaç
sayfasıdır. Örnek amaçlı yapılan bir değişkenin button’a tıklandığında,
1 arttırılıp o anki zamanla ekrana basıldığı sayfadır.
- @page “/counter” : routing amaçlı sayfaya nasıl erişileceği belirtilir.
- @code { } : ilgili C# kodlarının ve hatta sınıfların tanımlandığı yerdir.
- void IncrementCount() { currentCount++; } : button tıklanması ile çağrılacak olan methoddur. “currentCount” değişkeni bir arttırılır.
- <button @onclick=”IncrementCount”>Click me</button> : button’un tıklanma eventinde çağrılacak methodur.
- <p>Current count: @currentCount</p> : c# tarafında tanımlı değişken RazorViewEngine’inden dolayı “@” ile “@currentCount” şeklinde tanımlanır.
Pages/FetchData.razor : Bir servisten ya da json’dan çekilen hava
bilgisinin, ekrana basıldığı örnek bir Razor sayfadır.
- @page “/fetchdata” : routing amaçlı sayfaya erişim bu şeklinde tanımlanmıştır.
- “@inject HttpClient Http” : sayfa içerisinde “Http.GetFromJsonAsync()”
methodunun kullanılabilmesi için ilgili kütüphane eklenir.
- @code { WeatherForecast[] forecasts; } : @code içerisinde tanımlı
C# kodlarında, “Json”‘dan çekilecek data burda tanımlı WeatherForecast[]
dizisinde saklanacaktır.
- protected override async Task OnInitializedAsync() : sayfa asenkron olarak yüklenirken “sample-data/weather.json” datası yine asenkron çekilerek “<WeatherForecast[]>” tipinde “forecasts[]” değişkenine atanmaktadır. Ve işin en ilginç yanı bu kod client side tarafta yazılmakta ve browser tarafından backend’e ihtiyaç duyulmadan derlenmektedir.
- public class WeatherForecast : ilgili sınıf ve 4 property’si yine
“@code{}” içinde tanımlanmıştır. Sayfanın yukarısında Razor ile çekilen “WeatherForecast[]” datası ekrana klasik yol ile basılır.
- “@if (forecasts == null)” : asenkron olarak henüz bir kayıt çekilmemiş
ise sayfaya bu bölüm çalışır.
- else{} : kayıt var ise json’dan çekilen tüm data tek tek gezilir.
- “@forecast.Date.ToShortDateString()” : herbir kayıta ait tüm propertyler
ekrana “@” işareti ile basılır.
Wwwroot/sample-data/weather.json : Örnek Weather Json data.
Bir önceki yazıma aşağıdaki linkten ulaşabilirsiniz…
Kaynak kodlar…
Umarım faydalı bir yazı olmuştur. Herkese mutlu kodlamalar.
KAMİL KAPLAN ( Software Engineer)
Bir sonraki makalede görüşmek ümidi ile sağlıcakla kalın.