Blazor Hybrid Nedir ve Neden Önemli?
Web geliştirici misiniz ama bir yandan da mobil uygulama yapmanız gerekiyor? Ya da .NET ekosisteminde çalışıyorsunuz ama her platform için ayrı UI yazmak canınızı sıkıyor? Tam da bu noktada Blazor Hybrid sahneye çıkıyor.
Blazor Hybrid, Razor bileşenlerinin doğrudan cihaz üzerinde yerel olarak çalıştığı bir geliştirme modeli. Bileşenler, yerel bir interop kanalı aracılığıyla gömülü bir WebView kontrolüne render ediliyor. Burada önemli bir ayrım var: bileşenler tarayıcıda çalışmaz ve WebAssembly kullanılmaz. Tüm C# kodunuz doğrudan .NET çalışma zamanı üzerinde çalışır — yani tam yerel performans ve platform API'lerine doğrudan erişim elinizin altında.
Peki Cordova veya Ionic gibi geleneksel hibrit yaklaşımlardan farkı ne? Aslında oldukça temel bir fark var: Blazor Hybrid'de UI katmanı HTML/CSS ile oluşturulurken, iş mantığı tamamen yerel .NET sürecinde çalışıyor. WebView burada sadece render motoru olarak görev yapıyor, iş mantığını taşımıyor.
Bu yaklaşımın sağladığı avantajlara bir bakalım:
- Kod paylaşımı: Aynı Razor bileşenlerini web, mobil ve masaüstü uygulamalarında kullanabilirsiniz
- Web becerilerinin transferi: HTML, CSS ve JavaScript bilginiz doğrudan mobil geliştirmede işe yarar
- Yerel erişim: Kamera, GPS, dosya sistemi, push bildirimler gibi platform özelliklerine tam erişim
- Performans: C# kodu WebAssembly'ye derlenmez, doğrudan yerel çalışır — özellikle hesaplama yoğun işlemlerde fark ciddi şekilde hissediliyor
- Çevrimdışı çalışma: Uygulama yerel olarak yüklendiği için internet bağlantısı olmadan da çalışır
Proje Oluşturma ve İlk Yapılandırma
Hadi başlayalım. .NET MAUI Blazor Hybrid projesi oluşturmak için .NET 10 SDK ve Visual Studio 2022 (17.12+) ya da Visual Studio 2026 gerekiyor. Terminali açın ve şu komutu çalıştırın:
# Temel MAUI Blazor Hybrid projesi
dotnet new maui-blazor -n MobilUygulama
# Web ile paylaşımlı çözüm (önerilen)
dotnet new maui-blazor-web -n MobilUygulama
İkinci komutu tercih etmenizi öneririm — UI'yi web ve mobil arasında paylaşan tam bir çözüm oluşturuyor. Bu çözüm üç projeden oluşur:
- MobilUygulama: .NET MAUI Blazor Hybrid uygulaması (Android, iOS, macOS, Windows)
- MobilUygulama.Web: Blazor Web uygulaması
- MobilUygulama.Shared: Paylaşılan Razor bileşenlerini içeren sınıf kütüphanesi (RCL)
Proje Yapısı
Oluşturulan projenin temel yapısı şöyle görünüyor:
MobilUygulama/
├── Components/
│ ├── Layout/
│ │ ├── MainLayout.razor
│ │ └── NavMenu.razor
│ └── Pages/
│ ├── Home.razor
│ └── Counter.razor
├── Platforms/
│ ├── Android/
│ ├── iOS/
│ ├── MacCatalyst/
│ └── Windows/
├── Resources/
│ ├── Raw/
│ │ └── index.html
│ ├── Fonts/
│ └── Images/
├── wwwroot/
│ └── css/
├── App.xaml
├── App.xaml.cs
├── MainPage.xaml
├── MauiProgram.cs
└── Routes.razor
Burada birkaç kritik dosyaya dikkat etmekte fayda var. MainPage.xaml dosyası BlazorWebView kontrolünü barındırır, index.html Blazor uygulamasının HTML kök dosyasıdır ve MauiProgram.cs tüm servis kayıtlarının yapıldığı giriş noktasıdır.
BlazorWebView: Köprü Kontrol
BlazorWebView, .NET MAUI ile Blazor arasındaki köprüyü kuran kontrol. Açıkçası tüm sihir burada gerçekleşiyor. XAML içinde şöyle tanımlanıyor:
<!-- MainPage.xaml -->
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MobilUygulama"
x:Class="MobilUygulama.MainPage"
BackgroundColor="{DynamicResource PageBackgroundColor}">
<BlazorWebView x:Name="blazorWebView" HostPage="wwwroot/index.html">
<BlazorWebView.RootComponents>
<RootComponent Selector="#app" ComponentType="{x:Type local:Routes}" />
</BlazorWebView.RootComponents>
</BlazorWebView>
</ContentPage>
HostPage özelliği Blazor uygulamasının yükleneceği HTML dosyasını, RootComponents ise hangi Razor bileşeninin hangi CSS seçiciye bağlanacağını belirtir.
.NET 10 ile Gelen Web İstek Yakalama
.NET 10 ile birlikte güzel bir özellik geldi: BlazorWebView ve HybridWebView artık web isteklerini yakalayabiliyor. Yani uygulamanız bir URL'ye istek yaptığında araya girip başlıkları değiştirebilir, yönlendirme yapabilir ya da yerel yanıtlar sunabilirsiniz:
// MauiProgram.cs veya MainPage.xaml.cs
blazorWebView.WebViewInitializing += (sender, args) =>
{
// WebView oluşturulmadan önce platform ayarlarını yapılandır
#if ANDROID
args.Configuration.SetWebContentsDebuggingEnabled(true);
#endif
};
blazorWebView.WebViewInitialized += (sender, args) =>
{
// WebView oluşturulduktan sonra yerel örneğe erişim
#if ANDROID
args.WebView.Settings.JavaScriptEnabled = true;
args.WebView.Settings.DomStorageEnabled = true;
#elif IOS || MACCATALYST
args.WebView.Configuration.AllowsInlineMediaPlayback = true;
#endif
};
Razor Bileşenlerini Web ve Mobil Arasında Paylaşma
Blazor Hybrid'in bence en güçlü yanı burası: aynı Razor bileşenlerini hem web hem de mobil uygulamada kullanabiliyorsunuz. Bunun için paylaşılan bir Razor Class Library (RCL) oluşturmanız gerekiyor.
Paylaşılan Bileşen Örneği
@* MobilUygulama.Shared/Components/UrunKarti.razor *@
@using MobilUygulama.Shared.Models
<div class="urun-karti">
<img src="@Urun.ResimUrl" alt="@Urun.Ad" class="urun-resim" />
<div class="urun-bilgi">
<h3>@Urun.Ad</h3>
<p class="fiyat">@Urun.Fiyat.ToString("C2", new System.Globalization.CultureInfo("tr-TR"))</p>
<p class="aciklama">@Urun.Aciklama</p>
@if (PlatformBilgisi.MobilMi)
{
<button class="btn btn-primary" @onclick="SepeteEkle">
Sepete Ekle
</button>
}
else
{
<a href="/[email protected]" class="btn btn-primary">
Sepete Ekle
</a>
}
</div>
</div>
@code {
[Parameter] public UrunModel Urun { get; set; } = default!;
[Inject] private IPlatformBilgisi PlatformBilgisi { get; set; } = default!;
private async Task SepeteEkle()
{
// Mobilde doğrudan sepet servisini çağır
// Webde navigasyon ile sepet sayfasına yönlendir
}
}
Platform Farklılıklarını Yönetme
Web ve mobil arasındaki davranış farklılıklarını yönetmek için bir platform soyutlama katmanı oluşturmanız gerekiyor. Bu aslında klasik bir arayüz (interface) deseni — ama gerçekten işe yarıyor:
// MobilUygulama.Shared/Services/IPlatformBilgisi.cs
public interface IPlatformBilgisi
{
bool MobilMi { get; }
string PlatformAdi { get; }
string UygulamaSurumu { get; }
}
// MAUI uygulamasındaki implementasyon
// MobilUygulama/Services/MauiPlatformBilgisi.cs
public class MauiPlatformBilgisi : IPlatformBilgisi
{
public bool MobilMi => true;
public string PlatformAdi => DeviceInfo.Platform.ToString();
public string UygulamaSurumu => AppInfo.VersionString;
}
// Web uygulamasındaki implementasyon
// MobilUygulama.Web/Services/WebPlatformBilgisi.cs
public class WebPlatformBilgisi : IPlatformBilgisi
{
public bool MobilMi => false;
public string PlatformAdi => "Web";
public string UygulamaSurumu => "1.0.0";
}
Navigasyon Sistemi
Blazor Hybrid'de navigasyon, standart Blazor yönlendirmesini kullanır. Ancak bazen MAUI Shell navigasyonu ile Blazor navigasyonunu birlikte kullanmanız gereken senaryolar da çıkabiliyor.
Temel Blazor Navigasyonu
@* Routes.razor *@
<Router AppAssembly="typeof(Routes).Assembly"
AdditionalAssemblies="new[] { typeof(MobilUygulama.Shared._Imports).Assembly }">
<Found Context="routeData">
<RouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)" />
<FocusOnNavigate RouteData="routeData" Selector="h1" />
</Found>
<NotFound>
<LayoutView Layout="typeof(Layout.MainLayout)">
<p role="alert">Sayfa bulunamadı.</p>
</LayoutView>
</NotFound>
</Router>
Programatik Navigasyon
@page "/urunler"
@inject NavigationManager Navigasyon
<h2>Ürün Listesi</h2>
<button @onclick="DetaySayfasinaGit">Ürün Detayı</button>
@code {
private void DetaySayfasinaGit()
{
Navigasyon.NavigateTo("/urun/42");
}
}
Yerel MAUI Servisleriyle Navigasyon Entegrasyonu
Blazor içinden yerel MAUI servislerine erişmek mi istiyorsunuz? BlazorWebView kontrolünün TryDispatchAsync metodunu kullanabilirsiniz, ama açıkçası daha temiz bir yaklaşım var: DI üzerinden paylaşılan servisler tanımlamak.
// MobilUygulama/Services/MobilNavigasyonServisi.cs
public class MobilNavigasyonServisi : INavigasyonServisi
{
public async Task PaylasBildirimGoster(string mesaj)
{
await Share.Default.RequestAsync(new ShareTextRequest
{
Text = mesaj,
Title = "Paylaş"
});
}
public async Task KonumAc(double enlem, double boylam)
{
var konum = new Location(enlem, boylam);
var secenekler = new MapLaunchOptions
{
NavigationMode = NavigationMode.Driving
};
await Map.Default.OpenAsync(konum, secenekler);
}
}
Yerel Platform Özelliklerine Erişim
İşte Blazor Hybrid'in gerçek gücünün ortaya çıktığı yer burası. Razor bileşenlerinden doğrudan yerel platform API'lerine erişebiliyorsunuz. Gelin yaygın kullanılan bazı platform özelliklerine ve nasıl entegre edileceğine bakalım.
Kamera ve Fotoğraf Seçimi
// Services/IKameraServisi.cs
public interface IKameraServisi
{
Task<byte[]?> FotografCekAsync();
Task<byte[]?> GalerideSecAsync();
}
// Services/MauiKameraServisi.cs
public class MauiKameraServisi : IKameraServisi
{
public async Task<byte[]?> FotografCekAsync()
{
if (!MediaPicker.Default.IsCaptureSupported)
return null;
var foto = await MediaPicker.Default.CapturePhotoAsync();
if (foto is null) return null;
using var akis = await foto.OpenReadAsync();
using var bellekAkisi = new MemoryStream();
await akis.CopyToAsync(bellekAkisi);
return bellekAkisi.ToArray();
}
public async Task<byte[]?> GalerideSecAsync()
{
var foto = await MediaPicker.Default.PickPhotoAsync();
if (foto is null) return null;
using var akis = await foto.OpenReadAsync();
using var bellekAkisi = new MemoryStream();
await akis.CopyToAsync(bellekAkisi);
return bellekAkisi.ToArray();
}
}
Razor Bileşeninden Kamera Kullanımı
@page "/profil"
@inject IKameraServisi KameraServisi
<h2>Profil Fotoğrafı</h2>
@if (profilResmi is not null)
{
<img src="@profilResmiUrl" alt="Profil" class="profil-resim" />
}
<div class="btn-grup">
<button class="btn btn-primary" @onclick="FotografCek">
Fotoğraf Çek
</button>
<button class="btn btn-secondary" @onclick="GaleridenSec">
Galeriden Seç
</button>
</div>
@code {
private byte[]? profilResmi;
private string? profilResmiUrl;
private async Task FotografCek()
{
profilResmi = await KameraServisi.FotografCekAsync();
if (profilResmi is not null)
{
profilResmiUrl = $"data:image/png;base64,{Convert.ToBase64String(profilResmi)}";
}
}
private async Task GaleridenSec()
{
profilResmi = await KameraServisi.GalerideSecAsync();
if (profilResmi is not null)
{
profilResmiUrl = $"data:image/png;base64,{Convert.ToBase64String(profilResmi)}";
}
}
}
Konum Servisi Entegrasyonu
// Services/MauiKonumServisi.cs
public class MauiKonumServisi : IKonumServisi
{
public async Task<KonumBilgisi?> MevcutKonumuAlAsync()
{
var izin = await Permissions.CheckStatusAsync<Permissions.LocationWhenInUse>();
if (izin != PermissionStatus.Granted)
{
izin = await Permissions.RequestAsync<Permissions.LocationWhenInUse>();
if (izin != PermissionStatus.Granted)
return null;
}
var konum = await Geolocation.Default.GetLocationAsync(
new GeolocationRequest
{
DesiredAccuracy = GeolocationAccuracy.High,
Timeout = TimeSpan.FromSeconds(30)
});
if (konum is null) return null;
return new KonumBilgisi
{
Enlem = konum.Latitude,
Boylam = konum.Longitude,
Dogruluk = konum.Accuracy
};
}
}
Dependency Injection Yapılandırması
Tüm servislerin DI konteynerine kaydedilmesi MauiProgram.cs dosyasında yapılıyor. Burası projenin kalbi diyebiliriz. İşte kapsamlı bir yapılandırma örneği:
// MauiProgram.cs
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
});
// Blazor WebView
builder.Services.AddMauiBlazorWebView();
#if DEBUG
builder.Services.AddBlazorWebViewDeveloperTools();
builder.Logging.AddDebug();
#endif
// Platform servisleri
builder.Services.AddSingleton<IPlatformBilgisi, MauiPlatformBilgisi>();
builder.Services.AddSingleton<IKameraServisi, MauiKameraServisi>();
builder.Services.AddSingleton<IKonumServisi, MauiKonumServisi>();
// API ve veri servisleri
builder.Services.AddSingleton<IApiServisi, ApiServisi>();
builder.Services.AddSingleton<IYerelDepolamaServisi, YerelDepolamaServisi>();
// HttpClient yapılandırması
builder.Services.AddHttpClient("API", client =>
{
client.BaseAddress = new Uri("https://api.ornekuygulama.com/");
client.DefaultRequestHeaders.Add("Accept", "application/json");
});
return builder.Build();
}
}
Kimlik Doğrulama (Authentication)
Şimdi gelelim biraz daha karmaşık ama bir o kadar da önemli bir konuya. Blazor Hybrid'de kimlik doğrulama, standart Blazor web uygulamalarından biraz farklı çalışıyor. MAUI uygulamaları cookie tabanlı kimlik doğrulama ile çalışamıyor, o yüzden bearer token yaklaşımını kullanmamız gerekiyor.
Özel AuthenticationStateProvider
// Services/MobilKimlikDogrulamaProvider.cs
using System.Security.Claims;
using Microsoft.AspNetCore.Components.Authorization;
public class MobilKimlikDogrulamaProvider : AuthenticationStateProvider
{
private readonly IYerelDepolamaServisi _depolama;
private ClaimsPrincipal _mevcutKullanici = new(new ClaimsIdentity());
public MobilKimlikDogrulamaProvider(IYerelDepolamaServisi depolama)
{
_depolama = depolama;
}
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
{
var token = await _depolama.TokenAlAsync();
if (string.IsNullOrEmpty(token))
{
return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
}
// Token'dan claim'leri çöz
var claims = TokenCozumleyici.ClaimleriAl(token);
var kimlik = new ClaimsIdentity(claims, "Bearer");
_mevcutKullanici = new ClaimsPrincipal(kimlik);
return new AuthenticationState(_mevcutKullanici);
}
public async Task GirisYapAsync(string kullaniciAdi, string sifre)
{
// API'den token al
var token = await ApidenTokenAlAsync(kullaniciAdi, sifre);
await _depolama.TokenKaydetAsync(token);
var claims = TokenCozumleyici.ClaimleriAl(token);
var kimlik = new ClaimsIdentity(claims, "Bearer");
_mevcutKullanici = new ClaimsPrincipal(kimlik);
NotifyAuthenticationStateChanged(
Task.FromResult(new AuthenticationState(_mevcutKullanici)));
}
public async Task CikisYapAsync()
{
await _depolama.TokenSilAsync();
_mevcutKullanici = new ClaimsPrincipal(new ClaimsIdentity());
NotifyAuthenticationStateChanged(
Task.FromResult(new AuthenticationState(_mevcutKullanici)));
}
private async Task<string> ApidenTokenAlAsync(string kullaniciAdi, string sifre)
{
// HTTP çağrısı ile API'den JWT token alınır
// Gerçek implementasyonda HttpClient kullanılır
throw new NotImplementedException();
}
}
Kimlik Doğrulamanın DI'a Kaydedilmesi
// MauiProgram.cs içinde ekleyin
builder.Services.AddAuthorizationCore();
builder.Services.AddScoped<MobilKimlikDogrulamaProvider>();
builder.Services.AddScoped<AuthenticationStateProvider>(
sp => sp.GetRequiredService<MobilKimlikDogrulamaProvider>());
Yetkilendirme ile Sayfa Koruması
Servisi kaydettikten sonra sayfalarınızı koruma altına almak oldukça basit:
@* Routes.razor - Yetkilendirme desteği ile *@
<Router AppAssembly="typeof(Routes).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="routeData"
DefaultLayout="typeof(Layout.MainLayout)">
<NotAuthorized>
<RedirectToLogin />
</NotAuthorized>
</AuthorizeRouteView>
<FocusOnNavigate RouteData="routeData" Selector="h1" />
</Found>
</Router>
@* Korumalı sayfa örneği *@
@page "/siparislerim"
@attribute [Authorize]
<h2>Siparişlerim</h2>
<AuthorizeView>
<Authorized>
<p>Hoş geldiniz, @context.User.Identity?.Name</p>
<SiparisListesi />
</Authorized>
<NotAuthorized>
<p>Bu sayfayı görmek için giriş yapmalısınız.</p>
</NotAuthorized>
</AuthorizeView>
Performans İpuçları ve En İyi Uygulamalar
Blazor Hybrid uygulamalarında performansı üst düzeyde tutmak için dikkat etmeniz gereken bazı kritik noktalar var. Bunları göz ardı etmeyin, çünkü özellikle büyük projelerde farkı net şekilde hissedersiniz.
Render Performansı
@* Gereksiz render'ları önlemek için ShouldRender kullanın *@
@code {
private bool _guncellemeGerekli = true;
protected override bool ShouldRender() => _guncellemeGerekli;
private void VeriGuncelle()
{
// Sadece gerçekten değişiklik olduğunda render tetikle
_guncellemeGerekli = true;
StateHasChanged();
_guncellemeGerekli = false;
}
}
@* Büyük listelerde Virtualize bileşenini kullanın *@
<Virtualize Items="urunListesi" Context="urun">
<UrunKarti Urun="urun" />
</Virtualize>
Özellikle Virtualize bileşeni büyük listelerde hayat kurtarıcı olabiliyor. Binlerce öğeyi render etmek yerine sadece görünür olanları işliyor — performans farkı inanılmaz.
Resim Optimizasyonu
WebView içinde büyük resimleri base64 olarak render etmek bellek sorunlarına yol açabiliyor. Bunu zor yoldan öğrenebilirsiniz (ben öğrendim). Bunun yerine yerel dosya yollarını kullanın:
// Resmi önce yerel dosya sistemine kaydedin
var dosyaYolu = Path.Combine(FileSystem.CacheDirectory, "profil.jpg");
await File.WriteAllBytesAsync(dosyaYolu, resimVerisi);
// Blazor'da yerel dosya URL'si olarak kullanın
var resimUrl = dosyaYolu;
JavaScript Interop Kullanımı
Bazen JavaScript kütüphaneleri ya da tarayıcı API'leri kullanmanız gerekebilir. İyi haber şu ki Blazor Hybrid'de JS Interop tam olarak destekleniyor:
@inject IJSRuntime JS
@code {
protected override async Task OnAfterRenderAsync(bool ilkRender)
{
if (ilkRender)
{
// JavaScript fonksiyonu çağır
await JS.InvokeVoidAsync("haritaBaslat", enlem, boylam);
}
}
}
.NET 11 ile Gelecek Yenilikler
.NET 11 Preview sürümünde Blazor Hybrid ile ilgili bazı heyecan verici gelişmeler duyuruldu. Kısaca özetleyelim:
- XAML Source Generation varsayılan: .NET MAUI'de XAML kaynak üreteci artık varsayılan olarak etkin — derleme süresi ve çalışma zamanı performansı gözle görülür şekilde iyileşiyor
- CoreCLR Android'de varsayılan: Release yapılarında CoreCLR artık Android için varsayılan çalışma zamanı, Mono'ya kıyasla daha iyi performans sunuyor
- Etkileşimli hedef çerçeve seçimi:
dotnet runkomutuyla etkileşimli olarak hedef çerçeve ve cihaz seçimi yapılabiliyor - Runtime Async: .NET 11'in belki de en büyük yeniliği olan Runtime Async, async metot yönetimini derleyiciden çalışma zamanına taşıyor — bu da tüm Blazor bileşenlerinde daha iyi async performans anlamına geliyor
Gerçek Dünya Senaryosu: E-Ticaret Uygulaması
Peki tüm bu kavramları bir arada nasıl kullanıyoruz? Basit bir e-ticaret senaryosu üzerinden gösterelim. Bu örnek, web ve mobil arasında UI paylaşımını, yerel platform erişimini ve kimlik doğrulamayı bir arada kullanıyor:
// MobilUygulama.Shared/Services/ISepetServisi.cs
public interface ISepetServisi
{
Task<List<SepetOgesi>> SepetAlAsync();
Task SepeteEkleAsync(int urunId, int miktar);
Task SepettenCikarAsync(int urunId);
Task<decimal> ToplamHesaplaAsync();
}
// MAUI implementasyonu - yerel depolama kullanır
public class MobilSepetServisi : ISepetServisi
{
private readonly IYerelDepolamaServisi _depolama;
private List<SepetOgesi> _sepet = new();
public MobilSepetServisi(IYerelDepolamaServisi depolama)
{
_depolama = depolama;
}
public async Task<List<SepetOgesi>> SepetAlAsync()
{
_sepet = await _depolama.VeriAlAsync<List<SepetOgesi>>("sepet")
?? new List<SepetOgesi>();
return _sepet;
}
public async Task SepeteEkleAsync(int urunId, int miktar)
{
var mevcut = _sepet.FirstOrDefault(x => x.UrunId == urunId);
if (mevcut is not null)
{
mevcut.Miktar += miktar;
}
else
{
_sepet.Add(new SepetOgesi { UrunId = urunId, Miktar = miktar });
}
await _depolama.VeriKaydetAsync("sepet", _sepet);
}
public async Task SepettenCikarAsync(int urunId)
{
_sepet.RemoveAll(x => x.UrunId == urunId);
await _depolama.VeriKaydetAsync("sepet", _sepet);
}
public Task<decimal> ToplamHesaplaAsync()
{
return Task.FromResult(_sepet.Sum(x => x.BirimFiyat * x.Miktar));
}
}
Sık Sorulan Sorular (FAQ)
Blazor Hybrid uygulamalar çevrimdışı çalışır mı?
Evet, kesinlikle. Blazor Hybrid uygulamalar tamamen çevrimdışı çalışabilir çünkü uygulama yerel olarak cihaza yüklenmiş durumda. Ancak API çağrıları gibi ağ gerektiren işlemler için çevrimdışı stratejiler (yerel önbellekleme, kuyruk mekanizması gibi) uygulamanız gerekecek.
Blazor Hybrid ile Blazor WebAssembly arasındaki fark nedir?
Blazor WebAssembly'de C# kodu tarayıcıda WebAssembly olarak çalışır ve platform API'lerine erişemez. Blazor Hybrid'de ise C# kodu yerel .NET çalışma zamanında çalışır, WebView sadece render için kullanılır. Sonuç olarak yerel API'lere tam erişim, daha hızlı başlatma süresi ve daha iyi performans elde ediyorsunuz.
Blazor Hybrid performansı yerel MAUI XAML uygulamalarına kıyasla nasıl?
UI render performansında XAML tabanlı yerel kontroller genellikle daha hızlıdır — bu doğru, çünkü doğrudan platform kontrollerini kullanıyorlar. Ama iş mantığı performansında hiçbir fark yok, her iki durumda da kod yerel .NET çalışma zamanında çalışıyor. Çoğu uygulama için bu render performans farkı, kullanıcı tarafından fark edilemez düzeyde kalıyor.
Mevcut bir Blazor web uygulamasını Blazor Hybrid'e taşıyabilir miyim?
Evet, ve bu aslında Blazor Hybrid'in en güzel avantajlarından biri. Mevcut Razor bileşenlerinizi bir Razor Class Library'ye taşıyarak hem web hem de MAUI uygulamasında kullanabilirsiniz. Platform spesifik özellikler (dosya erişimi, kamera gibi) için servis soyutlamaları oluşturmanız yeterli.
.NET MAUI Blazor Hybrid hangi platformları destekler?
.NET MAUI Blazor Hybrid şu platformları destekliyor: Android 5.0 (API 21) ve üzeri, iOS 15 ve üzeri, macOS 12 (Monterey) ve üzeri, Windows 10 sürüm 1809 ve üzeri. Windows'ta WebView2 çalışma zamanı gerekli. Ayrıca maui-blazor-web şablonuyla web platformunu da hedefleyebilirsiniz.