A’dan Z’ye Blazor Öğreniyorum…

{Kamil Kaplan} ®
Kodcular
Published in
10 min readApr 30, 2020

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.

  1. Visual Studio Kurulumu
https://visualstudio.microsoft.com/downloads/

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
WebAssembly yüklemesi gerçekleşmiştir.

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.

ŞEKİL 1 : Create a new project

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.

ŞEKİL 2 : Blazor App

Ş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.

ŞEKİL 3 : Project name -> Create

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.

ŞEKİL 4 : Çalışma Ortamı Seçilip -> Create ile devam ediyoruz.
ŞEKİL 5 : Projemiz oluşturuluyor.

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.

ŞEKİL 6 : Program dosyaları

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 çıkacak HTML'i dinamikleştirmek ve HTML'e destek verecek 'Code' için kullanmamızı sağlamasıdır. Tamamıyla göresellikle ilgi kısımda razor'dan yararlanıyoruz.

Bir şablon olarak gelen uygulamamız çalıştıralım ve sonucu görelim. F5 veya IIS Ecpress çalıştırabiliriz.

ŞEKİL 7 : Uygulamanın çalıştırılması
ŞEKİL 8 : Uygulamamız çalıştı…

Şimdi projemizi inceleyelim. Solda bir menu ve üstte bir navigation var aslında bu bizim layout’umuz.

ŞEKİL 9 : Index.razor
ŞEKİL 10 : Counter.razor

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.

ŞEKİL 11 : Index.razor Chrome görünümü

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.

ŞEKİL 12 : SurveyPrompt.razor

İ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.

ŞEKİL 13 : Counter.razor

Ö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.

ŞEKİL 14 : Counter.razor - Örnek Çalışma
ŞEKİL 15 : Counter.razor - Chrome görünümü
ŞEKİL 16 : Counter.razor — Chrome görünümü

Index.razor ve Counter.razor componentlerimizi inceledikten sonra şimdi FetchData.razor componentimizi inceleyip, öncelikle bu component’i açıyoruz.

ŞEKİL 17 : FetchData.razor

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.

ŞEKİL 18 : FetchData.razor - @code bölümü

@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.

ŞEKİL 19 : FetchData.razor - html bölümü

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.

App.razor

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.

Program.cs

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.

wwwroot/index.html

Imports.razor : Tüm sayfalarda kullanılacak .Net ve diğer kütüphaneler burada tanımlanır.

_Import.razor

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.

MainLayout.razor

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.

NavMenu.razor

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.

SurveyPropmt.razor

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.

Index.razor

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.

Counter.razor

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.

FetchData.razor

Wwwroot/sample-data/weather.json : Örnek Weather Json data.

weather.json

Umarım faydalı bir yazı olmuştur. Herkese mutlu kodlamalar.
KAMİL KAPLAN ( Software Engineer)

--

--