Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Uyarı
ASP.NET Core'un bu sürümü artık desteklenmiyor. Daha fazla bilgi için bkz . .NET ve .NET Core Destek İlkesi. Geçerli sürüm için bu makalenin .NET 9 sürümüne bakın.
Bu makalede, işlenmeyen özel durumları yönetme Blazor ve hataları algılayıp işleyen uygulamalar geliştirme açıklanmaktadır.
Geliştirme sırasında ayrıntılı hatalar
Uygulama Blazor geliştirme sırasında düzgün çalışmadığında, uygulamadan ayrıntılı hata bilgileri almak sorunu gidermeye ve düzeltmeye yardımcı olur. Bir hata oluştuğunda uygulamalar ekranın Blazor alt kısmında açık sarı bir çubuk görüntüler:
- Geliştirme sırasında çubuk sizi özel durumu görebileceğiniz tarayıcı konsoluna yönlendirir.
- Üretimde, çubuk kullanıcıya bir hata oluştuğu konusunda uyarır ve tarayıcının yenilenmesini önerir.
Bu hata işleme deneyiminin kullanıcı arabirimi, proje şablonlarının Blazorbir parçasıdır. Projelerin
Blazor Web App içinde, MainLayout
bileşenindeki deneyimi özelleştirin.
Ortam Etiketi Yardımcısı (örneğin, <environment include="Production">...</environment>
) Razor bileşenlerinde desteklenmediğinden, aşağıdaki örnek, farklı ortamlar için hata iletilerini yapılandırmak amacıyla IHostEnvironment’yi kullanır.
üst kısmında MainLayout.razor
:
@inject IHostEnvironment HostEnvironment
Hata arayüzü işaretlemesini oluşturun veya değiştirin:
<div id="blazor-error-ui" data-nosnippet>
@if (HostEnvironment.IsProduction())
{
<span>An error has occurred.</span>
}
else
{
<span>An unhandled exception occurred.</span>
}
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>
Bir Blazor Server uygulamada, Pages/_Host.cshtml
dosyasında deneyimi özelleştirin. Aşağıdaki örnek, farklı ortamlar için hata iletilerini yapılandırmak için Ortam Etiketi Yardımcısı'nı kullanır.
Bir Blazor Server uygulamada, Pages/_Layout.cshtml
dosyasında deneyimi özelleştirin. Aşağıdaki örnek, farklı ortamlar için hata iletilerini yapılandırmak için Ortam Etiketi Yardımcısı'nı kullanır.
Bir Blazor Server uygulamada, Pages/_Host.cshtml
dosyasında deneyimi özelleştirin. Aşağıdaki örnek, farklı ortamlar için hata iletilerini yapılandırmak için Ortam Etiketi Yardımcısı'nı kullanır.
Blazor hata kullanıcı arabirimi işaretlemesini oluşturun veya değiştirin.
<div id="blazor-error-ui" data-nosnippet>
<environment include="Staging,Production">
An error has occurred.
</environment>
<environment include="Development">
An unhandled exception occurred.
</environment>
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>
Bir Blazor WebAssembly uygulamada, wwwroot/index.html
dosyasında deneyimi özelleştirin.
<div id="blazor-error-ui" data-nosnippet>
An unhandled error has occurred.
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>
blazor-error-ui
öğesi, uygulamanın otomatik olarak oluşturulan stil sayfasında blazor-error-ui
CSS sınıfının display: none
stili bulunduğundan genellikle gizli tutulur. Bir hata oluştuğunda, çerçeve display: block
etiketi öğeye uygular.
blazor-error-ui
öğesi, wwwroot/css
klasöründeki sitenin stil sayfasında yer alan CSS sınıfının blazor-error-ui
stiline display: none
sahip olmasından dolayı normalde gizlenir. Bir hata oluştuğunda, çerçeve display: block
elementine uygular.
Ayrıntılı bağlantı hattı hataları
Bu bölüm, bir devre üzerinden çalışan Blazor Web Appler için geçerlidir.
Bu bölüm uygulamalar için Blazor Server geçerlidir.
İstemci tarafı hataları çağrı yığınını içermez ve hatanın nedeni hakkında ayrıntılı bilgi sağlamaz, ancak sunucu günlükleri bu tür bilgileri içerir. Geliştirme amacıyla hassas devre hata bilgileri, ayrıntılı hatalar etkinleştirilerek istemciye sunulabilir.
CircuitOptions.DetailedErrors seçeneğini true
olarak ayarlayın. Daha fazla bilgi ve örnek için bkz . ASP.NET Temel BlazorSignalR kılavuzu.
Uygulamanın Development
ortam ayarları dosyasında, DetailedErrors
yapılandırma anahtarını true
olarak ayarlamak, CircuitOptions.DetailedErrors ayarına bir alternatiftir. Ayrıca, ayrıntılı SignalR günlük kaydı için SignalR sunucu tarafı günlüğünüMicrosoft.AspNetCore.SignalR
Hata Ayıklama veya İz olarak ayarlayın.
appsettings.Development.json
:
{
"DetailedErrors": true,
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information",
"Microsoft.AspNetCore.SignalR": "Debug"
}
}
}
Yapılandırma DetailedErrors anahtarı, Development
/Staging
ortam sunucularında veya yerel sisteminizde ASPNETCORE_DETAILEDERRORS
ortam değişkeni kullanılarak true
olarak true
değeriyle de ayarlanabilir.
Uyarı
Hata bilgilerini İnternet'te istemcilere ifşa etmekten her zaman kaçının; bu bir güvenlik riskidir.
Sunucu tarafı işleme bileşeni için Razor detaylı hatalar
Bu bölüm s için Blazor Web Appgeçerlidir.
RazorComponentsServiceOptions.DetailedErrors Bileşen sunucu tarafı işleme hataları hakkında ayrıntılı bilgi oluşturmayı denetlemek için Razor seçeneğini kullanın. Varsayılan değer şudur: false
.
Aşağıdaki örnek ayrıntılı hataları gösterir.
builder.Services.AddRazorComponents(options =>
options.DetailedErrors = builder.Environment.IsDevelopment());
Uyarı
Yalnızca Development
ortamında ayrıntılı hataları etkinleştirin. Ayrıntılı hatalar, kötü amaçlı kullanıcıların bir saldırıda kullanabileceği uygulama hakkında hassas bilgiler içerebilir.
Yukarıdaki örnek, DetailedErrors'nın değerini, IsDevelopment tarafından döndürülen değere göre ayarlayarak bir güvenlik derecesi sağlar. Uygulama Development
ortamdayken, DetailedErrorstrue
olarak ayarlanır. Üretim uygulamasını ortamdaki genel bir sunucuda Development
barındırmak mümkün olduğundan bu yaklaşım kusursuz değildir.
Geliştirici kodunda işlenmeyen özel durumları yönetme
Bir uygulamanın hatadan sonra devam etmesi için uygulamanın hata işleme mantığı olmalıdır. Bu makalenin sonraki bölümlerinde işlenmeyen özel durumların olası kaynakları açıklanmaktadır.
Üretimde, framework hata mesajlarını veya yığın izlerini kullanıcı arayüzünde göstermeyin. Özel durum iletilerinin veya yığın izlerinin işlenmesi şu sonuçlara yol açabilir:
- Hassas bilgileri son kullanıcılara ifşa etme.
- Kötü amaçlı bir kullanıcının uygulama, sunucu veya ağ güvenliğini tehlikeye atabilecek zayıflıkları bulmasına yardımcı olun.
Devreler için işlenmeyen istisnalar
Bu bölüm, bir bağlantı hattı üzerinde çalışan sunucu tarafı uygulamaları için geçerlidir.
Razor sunucu etkileşiminin etkinleştirildiği bileşenler sunucuda durumsaldır. Kullanıcılar sunucudaki bileşenle etkileşim kurarken, bağlantı hattı olarak bilinen sunucuyla bağlantı kurar. Devre, etkin bileşen örneklerinin yanı sıra aşağıdakiler gibi diğer birçok durum yönünü barındırıyor:
- Bileşenlerin en son işlenen çıktısı.
- İstemci tarafı olaylar tarafından tetiklenebilecek olay işleme temsilcilerinin mevcut kümesi.
Bir kullanıcı uygulamayı birden çok tarayıcı sekmesinde açarsa, kullanıcı birden çok bağımsız devre oluşturur.
Blazor çoğu işlenmeyen özel durumu, oluştukları devre için ölümcül kabul eder. İşlenmeyen bir özel durum nedeniyle bir bağlantı hattı sonlandırılırsa, kullanıcı yalnızca sayfayı yeniden yükleyerek yeni bir bağlantı hattı oluşturarak uygulamayla etkileşim kurmaya devam edebilir. Sonlandırılan devrenin dışında kalan ve diğer kullanıcıların veya diğer tarayıcı sekmelerinin devreleri olan devreler etkilenmez. Bu senaryo, çöken bir masaüstü uygulamasına benzer. Kilitlenen uygulamanın yeniden başlatılması gerekir, ancak diğer uygulamalar etkilenmez.
Aşağıdaki nedenlerle işlenmeyen bir özel durum oluştuğunda çerçeve bir bağlantı hattını sonlandırır:
- İşlenmeyen bir özel durum genellikle devreyi tanımsız durumda bırakır.
- İşlenmeyen bir özel durumdan sonra uygulamanın normal çalışması garanti edilemez.
- Bağlantı hattı tanımlanmamış durumda devam ederse uygulamada güvenlik açıkları görüntülenebilir.
Genel özel durum işleme
Genel olarak özel durumları işleme yaklaşımları için aşağıdaki bölümlere bakın:
- Hata sınırları: Tüm Blazor uygulamalar için geçerlidir.
- Alternatif genel özel durum işleme: Genel etkileşimli işleme modunu benimseyen Blazor Server, Blazor WebAssembly ve 8.0 veya üzeri Blazor Web Appler için geçerlidir.
Hata sınırları
Hata sınırları , özel durumları işlemek için kullanışlı bir yaklaşım sağlar. Bileşen ErrorBoundary :
- Bir hata oluşmadığında alt içeriğini işler.
- Hata sınırındaki herhangi bir bileşen tarafından işlenmeyen bir özel durum oluştuğunda hata arayüzünü gösterir.
Hata sınırı tanımlamak için ErrorBoundary bileşenini kullanarak bir veya daha fazla diğer bileşeni sarın. Hata sınırı, sarmaladığı bileşenler tarafından oluşan işlenmeyen özel durumları yönetir.
<ErrorBoundary>
...
</ErrorBoundary>
Genel bir şekilde hata sınırı uygulamak için, uygulamanın ana düzeninin gövde içeriğinin çevresine sınırı ekleyin.
MainLayout.razor
içinde:
<article class="content px-4">
<ErrorBoundary>
@Body
</ErrorBoundary>
</article>
Blazor Web App hata sınırının yalnızca statik bir MainLayout
bileşene uygulandığı durumlarda, sınır yalnızca statik sunucu tarafı işleme (statik SSR) sırasında etkindir. Sınır, yalnızca bileşen hiyerarşisinin daha aşağısındaki bir bileşen etkileşimli olduğundan etkinleştirilmez.
Bileşenin MainLayout
parametresi rastgele kod olan ve serileştirilemediği bir Body
temsilci olduğundan, bileşene RenderFragment etkileşimli işleme modu uygulanamaz.
MainLayout
bileşeni ve bileşen hiyerarşisinin daha aşağısındaki bileşenlerin geri kalanı için etkileşimi geniş ölçekte etkinleştirmek için, uygulamanın genellikle HeadOutlet
bileşeni olan uygulamanın kök bileşenindeki Routes
ve App
bileşen örneklerine etkileşimli işleme modunu uygulayarak genel etkileşimli işleme modunu benimsemesi gerekir. Aşağıdaki örnek, Etkileşimli Sunucu (InteractiveServer
) işleme modunu genel olarak benimser.
Components/App.razor
içinde:
<HeadOutlet @rendermode="InteractiveServer" />
...
<Routes @rendermode="InteractiveServer" />
Genel etkileşimi etkinleştirmemek isterseniz hata sınırını bileşen hiyerarşisinin daha aşağısına yerleştirin. Akılda tutulması gereken önemli kavramlar, hata sınırının nereye yerleştirildiğidir:
- Hata sınırının yerleştirildiği bileşen etkileşimli değilse, hata sınırı yalnızca statik SSR sırasında sunucuda etkinleştirilebilme özelliğine sahiptir. Örneğin, bir bileşen yaşam döngüsü yönteminde bir hata oluştuğunda sınır etkinleştirilebilir, ancak bir düğme tıklama işleyicisi tarafından atılan bir hata gibi, bileşen içindeki kullanıcı etkileşimi tarafından tetiklenen bir olay için etkinleştirmez.
- Hata sınırının yerleştirildiği bileşen etkileşimliyse, hata sınırı, sardığı etkileşimli bileşenler için etkinleşebilir.
Not
Uygulamanın istemci tarafı işlemesi (CSR) tamamen etkileşimli olduğundan, önceki önemli noktalar tek başına Blazor WebAssembly uygulamalarla ilgili değildir.
Aşağıdaki örneği göz önünde bulundurun: Ekli sayaç bileşeni tarafından atılan bir özel durum, etkileşimli işleme modunu benimseyen Home
bileşenindeki bir hata sınırı tarafından yakalanıyor.
EmbeddedCounter.razor
:
<h1>Embedded Counter</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
if (currentCount > 5)
{
throw new InvalidOperationException("Current count is too big!");
}
}
}
Home.razor
:
@page "/"
@rendermode InteractiveServer
<PageTitle>Home</PageTitle>
<h1>Home</h1>
<ErrorBoundary>
<EmbeddedCounter />
</ErrorBoundary>
Gömülü bir sayaç bileşeni tarafından fırlatılan bir özel durumun, Home
bileşenindeki bir hata sınırı tarafından yakalandığı aşağıdaki örneği göz önünde bulundurun.
EmbeddedCounter.razor
:
<h1>Embedded Counter</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
if (currentCount > 5)
{
throw new InvalidOperationException("Current count is too big!");
}
}
}
Home.razor
:
@page "/"
<PageTitle>Home</PageTitle>
<h1>Home</h1>
<ErrorBoundary>
<EmbeddedCounter />
</ErrorBoundary>
İşlenmeyen özel durum beşin üzerinde bir currentCount
süre için oluşturulursa:
- Hata normal olarak günlüğe kaydedilir (
System.InvalidOperationException: Current count is too big!
). - Özel durum hata sınırı tarafından işlenir.
- Varsayılan hata arayüzü hata sınırı tarafından görüntülenir.
Bileşen, hata içeriği için blazor-error-boundary
CSS sınıfını kullanarak boş bir <div>
öğesi işler. Varsayılan kullanıcı arabiriminin renkleri, metni ve simgesi, uygulamanın klasördeki stil sayfasında wwwroot
tanımlanır, bu nedenle hata kullanıcı arabirimini özelleştirebilirsiniz.
Varsayılan hata içeriğini değiştirmek için:
- Hata sınırının bileşenlerini ChildContent özelliğine sar.
- ErrorContent özelliğini hata içeriği olarak ayarlayın.
Aşağıdaki örnek, EmbeddedCounter
bileşenini sarar ve özel hata içeriği sağlar.
<ErrorBoundary>
<ChildContent>
<EmbeddedCounter />
</ChildContent>
<ErrorContent>
<p class="errorUI">😈 A rotten gremlin got us. Sorry!</p>
</ErrorContent>
</ErrorBoundary>
Yukarıdaki örnekte, uygulamanın stil sayfası büyük olasılıkla içeriği stillendirmek için bir errorUI
CSS sınıfı içerir. Hata içeriği, blok düzeyi bir öğe olmadan ErrorContent özelliğinden işlenir. Bölme (<div>
) veya paragraf (<p>
) gibi blok düzeyinde bir öğe, hata içeriği işaretlemesini sarmalayabilir, ancak bu zorunlu değildir.
İsteğe bağlı olarak, hata verilerini elde etmek için ErrorContent bağlamındaki @context
'yı kullanın:
<ErrorContent>
@context.HelpLink
</ErrorContent>
ErrorContent aynı zamanda bağlamı adlandırabilir. Aşağıdaki örnekte, bağlam exception
olarak adlandırılır.
<ErrorContent Context="exception">
@exception.HelpLink
</ErrorContent>
Uyarı
Hata bilgilerini İnternet'te istemcilere ifşa etmekten her zaman kaçının; bu bir güvenlik riskidir.
Hata sınırı uygulamanın düzeninde tanımlanmışsa, hata oluştuktan sonra kullanıcının hangi sayfaya gidildiğine bakılmaksızın hata kullanıcı arabirimi görülür. Çoğu senaryoda hata sınırlarının kapsamını daraltmanızı öneririz. Bir hata sınırının kapsamını geniş kapsamlı olarak tanımlarsanız, hata sınırının Recover yöntemini çağırarak sonraki sayfa gezinti olaylarında hata olmayan bir duruma sıfırlayabilirsiniz.
MainLayout.razor
içinde:
- alanı ErrorBoundary, ona referans yakalamak için
@ref
öznitelik yönergesi ile ekleyin. - Yaşam döngüsü yönteminde
OnParameterSet
, kullanıcı farklı bir bileşene gittiği zaman hatayı temizlemek için ile Recover hata sınırında bir kurtarma tetikleyebilirsiniz.
...
<ErrorBoundary @ref="errorBoundary">
@Body
</ErrorBoundary>
...
@code {
private ErrorBoundary? errorBoundary;
protected override void OnParametersSet()
{
errorBoundary?.Recover();
}
}
Sonsuz döngüye girip kurtarma işleminin hatayı tekrar oluşturan bir bileşeni yeniden işlemesini önlemek için Recover'yi işleme mantığı içinde çağırmayın. Yalnızca şu durumlarda arayın: Recover
- Kullanıcı, bir yordamı yeniden denemek istediğini belirtmek için veya yeni bir bileşene gittiğinde, düğme seçme gibi bir UI hareketi gerçekleştirir.
- Çalıştırılan ek mantık aynı zamanda istisnayı da temizler. Bileşen yeniden başlatıldığında hata yinelenmez.
Aşağıdaki örnek, kullanıcının bir düğmeyle özel durumdan kurtulmasına izin verir.
<ErrorBoundary @ref="errorBoundary">
<ChildContent>
<EmbeddedCounter />
</ChildContent>
<ErrorContent>
<div class="alert alert-danger" role="alert">
<p class="fs-3 fw-bold">😈 A rotten gremlin got us. Sorry!</p>
<p>@context.HelpLink</p>
<button class="btn btn-info" @onclick="_ => errorBoundary?.Recover()">
Clear
</button>
</div>
</ErrorContent>
</ErrorBoundary>
@code {
private ErrorBoundary? errorBoundary;
}
ErrorBoundary öğesini alt sınıf olarak oluşturabilir ve özel işleme için OnErrorAsync öğesini geçersiz kılabilirsiniz. Aşağıdaki örnek hatayı sadece kaydeder, ancak istediğiniz hata işleme kodunu ekleyebilirsiniz. Kodunuz asenkron bir görevi bekliyorsa CompletedTask döndüren kod satırını kaldırabilirsiniz.
CustomErrorBoundary.razor
:
@inherits ErrorBoundary
@inject ILogger<CustomErrorBoundary> Logger
@if (CurrentException is null)
{
@ChildContent
}
else if (ErrorContent is not null)
{
@ErrorContent(CurrentException)
}
@code {
protected override Task OnErrorAsync(Exception ex)
{
Logger.LogError(ex, "😈 A rotten gremlin got us. Sorry!");
return Task.CompletedTask;
}
}
Yukarıdaki örnek bir sınıf olarak da uygulanabilir.
CustomErrorBoundary.cs
:
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
namespace BlazorSample;
public class CustomErrorBoundary : ErrorBoundary
{
[Inject]
ILogger<CustomErrorBoundary> Logger { get; set; } = default!;
protected override Task OnErrorAsync(Exception ex)
{
Logger.LogError(ex, "😈 A rotten gremlin got us. Sorry!");
return Task.CompletedTask;
}
}
Bir bileşende kullanılan önceki uygulamalardan biri:
<CustomErrorBoundary>
...
</CustomErrorBoundary>
Alternatif genel özel durum işleme
Bu bölümde açıklanan yaklaşım, genel etkileşimli işleme modunu (InteractiveServer
, InteractiveWebAssembly
veya InteractiveAuto
) benimseyen Blazor Server, Blazor WebAssembly ve Blazor Web App için geçerlidir. Yaklaşım, sayfa başına/bileşen işleme modlarını veya statik sunucu tarafı işlemeyi (statik SSR) benimseyenlerle çalışmaz çünkü işleme modu sınırları boyunca veya statik SSR'yi benimseyen bileşenlerle çalışmayan bir Blazor Web AppCascadingValue
/ öğesine bağlıdır.CascadingParameter
Hata sınırlarını () kullanmaya alternatif olarak, özel bir hata bileşenini CascadingValue
olarak alt bileşenlere iletmek mümkündür. Eklenen hizmeti veya özel günlükçü uygulamasını kullanmak yerine bir bileşeni kullanmanın avantajlarından biri, basamaklı bir bileşenin bir hata oluştuğunda içeriği işleyip CSS stilleri uygulayabilmesidir.
Aşağıdaki ProcessError
bileşen örneği yalnızca hataları günlüğe kaydeder, ancak bileşenin yöntemleri, birden çok hata işleme yönteminin kullanılması da dahil olmak üzere uygulama tarafından gerekli olan herhangi bir şekilde hataları işleyebilir.
ProcessError.razor
:
@inject ILogger<ProcessError> Logger
<CascadingValue Value="this">
@ChildContent
</CascadingValue>
@code {
[Parameter]
public RenderFragment? ChildContent { get; set; }
public void LogError(Exception ex)
{
Logger.LogError("ProcessError.LogError: {Type} Message: {Message}",
ex.GetType(), ex.Message);
// Call StateHasChanged if LogError directly participates in
// rendering. If LogError only logs or records the error,
// there's no need to call StateHasChanged.
//StateHasChanged();
}
}
Not
hakkında RenderFragmentdaha fazla bilgi için bkz . ASP.NET Core Razor bileşenleri.
Bu yaklaşımı bir Blazor Web App içinde kullanırken, Routes
bileşenini açın ve Router bileşenini ProcessError
bileşeni ile (<Router>...</Router>
) sarın. Bu, bileşenin, bileşenin ProcessError
olarak alındığı uygulamanın herhangi bir ProcessError
bileşenine art arda inmesine CascadingParameter
izin verir.
Routes.razor
içerisinde:
<ProcessError>
<Router ...>
...
</Router>
</ProcessError>
Bir Blazor Server veya Blazor WebAssembly uygulamasında bu yaklaşımı kullanırken, App
bileşenini açın ve Router bileşenini (<Router>...</Router>
) ProcessError
bileşeni ile sarın. Bu, ProcessError
bileşeninin, CascadingParameter
olarak alındığı uygulamanın herhangi bir ProcessError
bileşenine aktarılmasına izin verir.
App.razor
içinde:
<ProcessError>
<Router ...>
...
</Router>
</ProcessError>
Bir bileşendeki hataları işlemek için:
@code
bloğundakiProcessError
bileşeniniCascadingParameter
olarak belirleyin. Proje şablonunu temel alanCounter
bir uygulamadaki örnek Blazor bileşene aşağıdakiProcessError
özelliği ekleyin:[CascadingParameter] public ProcessError? ProcessError { get; set; }
Uygun bir özel durum türüne sahip herhangi bir
catch
blokta hata işleme yöntemini çağır. ÖrnekProcessError
bileşen yalnızca tekLogError
bir yöntem sunar, ancak hata işleme bileşeni uygulama genelinde alternatif hata işleme gereksinimlerini karşılamak için herhangi bir sayıda hata işleme yöntemi sağlayabilir. AşağıdakiCounter
bileşen@code
bloğu örneği basamaklı parametresiniProcessError
içerir ve sayı beşten büyük olduğunda günlüğe kaydetme için bir özel durum yakalar:@code { private int currentCount = 0; [CascadingParameter] public ProcessError? ProcessError { get; set; } private void IncrementCount() { try { currentCount++; if (currentCount > 5) { throw new InvalidOperationException("Current count is over five!"); } } catch (Exception ex) { ProcessError?.LogError(ex); } } }
Kaydedilen hata günlüğü:
fail: {COMPONENT NAMESPACE}.ProcessError[0]
ProcessError.LogError: System.InvalidOperationException Message: Current count is over five!
LogError
Yöntemi, özel bir hata iletisi çubuğu gösterme veya işlenen öğelerin CSS stillerini değiştirme gibi işlemeye doğrudan katılıyorsa, kullanıcı arabirimini yeniden oluşturmak için LogError
yönteminin sonunda StateHasChanged
çağrısını yapın.
Bu bölümdeki yaklaşımlar bir try-catch
deyimle ilgili hataları işlediğinden, bir hata oluştuğunda ve bağlantı hattı canlı kaldığında uygulamanın SignalR istemci ve sunucu arasındaki bağlantısı kopmuyor. İşlenmeyen diğer özel durumlar bir devre için ölümcül olmaya devam eder. Daha fazla bilgi için, devrenin işlenmeyen özel durumlara nasıl tepki vermesine ilişkin bölüme bakın.
Uygulama, hataları merkezi bir şekilde işlemek için bir hata işleme bileşenini basamaklı değer olarak kullanabilir.
Aşağıdaki ProcessError
bileşen kendisini bir CascadingValue
olarak alt bileşenlere geçirir. Aşağıdaki örnek yalnızca hatayı günlüğe kaydeder, ancak bileşenin yöntemleri, birden çok hata işleme yönteminin kullanılması da dahil olmak üzere uygulamanın gerektirdiği herhangi bir şekilde hataları işleyebilir. Eklenen hizmeti veya özel günlükçü uygulamasını kullanmak yerine bir bileşeni kullanmanın avantajlarından biri, basamaklı bir bileşenin bir hata oluştuğunda içeriği işleyip CSS stilleri uygulayabilmesidir.
ProcessError.razor
:
@using Microsoft.Extensions.Logging
@inject ILogger<ProcessError> Logger
<CascadingValue Value="this">
@ChildContent
</CascadingValue>
@code {
[Parameter]
public RenderFragment ChildContent { get; set; }
public void LogError(Exception ex)
{
Logger.LogError("ProcessError.LogError: {Type} Message: {Message}",
ex.GetType(), ex.Message);
}
}
Not
hakkında RenderFragmentdaha fazla bilgi için bkz . ASP.NET Core Razor bileşenleri.
Bileşende App
, Router bileşenini ProcessError
bileşeni ile sarın. Bu, ProcessError
bileşeninin, ProcessError
olarak alındığı herhangi bir uygulama bileşenine kademeli olarak yayılmasına izin verir.
App.razor
:
<ProcessError>
<Router ...>
...
</Router>
</ProcessError>
Bir bileşendeki hataları işlemek için:
@code
bloğundaProcessError
bileşeniniCascadingParameter
olarak belirleyin.[CascadingParameter] public ProcessError ProcessError { get; set; }
Uygun bir özel durum türüne sahip herhangi bir
catch
blokta hata işleme yöntemini çağır. ÖrnekProcessError
bileşen yalnızca tekLogError
bir yöntem sunar, ancak hata işleme bileşeni uygulama genelinde alternatif hata işleme gereksinimlerini karşılamak için herhangi bir sayıda hata işleme yöntemi sağlayabilir.try { ... } catch (Exception ex) { ProcessError.LogError(ex); }
Önceki örnek ProcessError
bileşeni ve LogError
yöntemi kullanılarak, tarayıcının geliştirici araçları konsolu yakalanan ve kaydedilen hatayı gösterir:
fail: {COMPONENT NAMESPACE}.Shared.ProcessError[0]
ProcessError.LogError: System.NullReferenceException Message: Object reference not set to an instance of an object.
LogError
Yöntemi, özel bir hata iletisi çubuğu gösterme veya işlenen öğelerin CSS stillerini değiştirme gibi işlemeye doğrudan katılıyorsa, kullanıcı arabirimini yeniden oluşturmak için LogError
yönteminin sonunda StateHasChanged
'i çağırın.
Bu bölümdeki yaklaşımlar bir try-catch
deyimle ilgili hataları işlediğinden, bir Blazor hata oluştuğunda ve bağlantı hattı canlı kaldığında uygulamanın SignalR istemci ile sunucu arasındaki bağlantısı kopmuyor. İşlenmeyen özel durumlar bir devre için ölümcüldür. Daha fazla bilgi için, devrenin işlenmeyen özel durumlara nasıl tepki vermesine ilişkin bölüme bakın.
Kalıcı bir sağlayıcı ile hataları günlüğe kaydetme
İşlenmeyen bir özel durum oluşursa, özel durum, hizmet kapsayıcısında yapılandırılan ILogger örneklerine kaydedilir. Blazor uygulamalar, Konsol Günlüğü Sağlayıcısı kullanılarak konsol çıkışını günlüğe kaydeder. Günlük boyutunu ve günlük döndürmeyi yöneten bir sağlayıcıyla sunucudaki bir konuma (veya istemci tarafı uygulamalar için arka uç web API'sine) günlük kaydı yapmayı göz önünde bulundurun. Alternatif olarak, uygulama bir Uygulama Performansı Yönetimi (APM) hizmeti, örneğin Azure Application Insights (Azure Monitor) kullanabilir.
Not
İstemci tarafı uygulamalarını desteklemek için yerel Application Insights özellikleri ve Google AnalyticsBlazoryerel çerçeve desteği, bu teknolojilerin gelecek sürümlerinde kullanılabilir hale gelebilir. Daha fazla bilgi için bkz . WASM İstemci Tarafında App Insights Blazor Desteği (microsoft/ApplicationInsights-dotnet #2143) ve Web analizi ve tanılama (topluluk uygulamalarına bağlantılar içerir) (dotnet/aspnetcore #5461). Bu arada, istemci tarafı bir uygulama, hataları doğrudan istemci tarafı uygulamasından Application Insights'a günlüğe kaydetmek için birlikte çalışma ile JS Application Insights JavaScript SDK'sını kullanabilir.
Bir bağlantı hattı üzerinden çalışan bir Blazor uygulamada geliştirme sırasında uygulama genellikle hata ayıklamaya yardımcı olmak için özel durumların tüm ayrıntılarını tarayıcının konsoluna gönderir. Üretimde, ayrıntılı hatalar istemcilere gönderilmez, ancak özel durumun tüm ayrıntıları sunucuda günlüğe kaydedilir.
Hangi olayların günlüğe kaydedileceğine ve günlüğe kaydedilen olayların önem düzeyine karar vermeniz gerekir. Saldırgan kullanıcılar hataları kasıtlı olarak tetikleyebilir. Örneğin, ürün ayrıntılarını görüntüleyen bir bileşenin URL'sinde bilinmeyen ProductId
bir hatanın bulunduğu bir hatayı günlüğe kaydetmeyin. Tüm hatalar günlüğe kaydedilecek olaylar olarak değerlendirilmemelidir.
Daha fazla bilgi için aşağıdaki makaleleri inceleyin:
- ASP.NET Core Blazor loglama
- ASP.NET Core'daki hataları işleme‡
- ASP.NET Core ile web API'leri oluşturma
‡Sunucu tarafı Blazor uygulamaları ve Blazor için web API arka uç uygulamaları olan diğer sunucu tarafı ASP.NET Core uygulamaları için geçerlidir. İstemci tarafı uygulamaları, istemcideki hata bilgilerini yakalayıp bir web API'sine gönderir; bu API de hata bilgilerini kalıcı bir günlük sağlayıcısına kaydeder.
İşlenmeyen bir özel durum oluşursa, bu özel durum ILogger, hizmet kapsayıcısında yapılandırılan örneklere kaydedilir. Blazor uygulamalar, Konsol Günlüğü Sağlayıcısı ile konsol çıktısını günlüğe kaydeder. Günlük boyutu yönetimi ve günlük döndürmesi olan bir günlük sağlayıcısı kullanan bir arka uç web API'sine hata bilgileri göndererek sunucuda daha kalıcı bir konuma oturum açmayı göz önünde bulundurun. Alternatif olarak, arka uç web API uygulaması, istemcilerden aldığı hata bilgilerini kaydetmek için Azure Uygulama Insights (Azure İzleyici)† gibi bir Uygulama Performansı Yönetimi (APM) hizmetini kullanabilir.
Hangi olayların günlüğe kaydedileceğine ve günlüğe kaydedilen olayların önem düzeyine karar vermeniz gerekir. Saldırgan kullanıcılar hataları kasıtlı olarak tetikleyebilir. Örneğin, ürün ayrıntılarını görüntüleyen bir bileşenin URL'sine bilinmeyen bir ProductId
sağlandığı durumlarda bir olayı günlüğe kaydetmeyin. Tüm hatalar kayıt altına alınacak olay olarak değerlendirilmemelidir.
Daha fazla bilgi için aşağıdaki makaleleri inceleyin:
- ASP.NET Core Blazor loglama
- ASP.NET Core'daki hataları işleme‡
- ASP.NET Core ile web API'leri oluşturma
†İstemci tarafı uygulamaları desteklemek için native Application Insights özellikleri ve native çerçeve desteği ile Google Analytics, bu teknolojilerin gelecekteki sürümlerinde kullanılabilir hale gelebilir. Daha fazla bilgi için bkz . WASM İstemci Tarafında App Insights Blazor Desteği (microsoft/ApplicationInsights-dotnet #2143) ve Web analizi ve tanılama (topluluk uygulamalarına bağlantılar içerir) (dotnet/aspnetcore #5461). Bu arada, istemci taraflı bir uygulama, hataları doğrudan Application Insights'a kaydetmek için Application Insights JavaScript SDK'sını birlikte çalışma ile kullanabilir.
‡Üzerinde Blazor olan uygulamalar için, sunucu tarafı ASP.NET Core uygulamaları web API arka uç uygulamaları olarak geçerlidir. İstemci tarafı uygulamalar hata bilgilerini yakalar ve bir web API'sine gönderir; bu API, hata bilgilerini kalıcı bir kayıt sağlayıcısına kaydeder.
Hataların oluşabileceği yerler
Çerçeve ve uygulama kodu, bu makalenin aşağıdaki bölümlerinde daha ayrıntılı olarak açıklanan aşağıdaki konumlardan herhangi birinde işlenmeyen özel durumlar tetikleyebilir:
Bileşen örneği oluşturulması
Bir bileşenin örneğini oluşturduğunda Blazor :
- Bileşenin kurucusu çağrılır.
- Bileşenin oluşturucusuna `
` yönergesi veya ` ` özniteliği ile sağlanan DI hizmetlerinin oluşturucuları çağrılır.
Yürütülen bir oluşturucuda veya herhangi [Inject]
bir özellik için ayarlayıcıda oluşan bir hata işlenmeyen bir özel durumla sonuçlanır ve çerçevenin bileşenin örneğini oluşturmasını durdurur. Uygulama bir bağlantı hattı üzerinden çalışıyorsa devre başarısız olur. Oluşturucu mantığı özel durumlar oluşturabilecekse, uygulama özel durumları hata yönetimi ve günlüğe kaydetme ile bir try-catch
deyimi kullanarak yakalamalı.
Yaşam döngüsü yöntemleri
Bir bileşenin ömrü boyunca yaşam Blazor döngüsü yöntemlerini çağırır. Bir ömür döngüsü yöntemi, senkron veya asenkron bir istisna oluşturursa, bu istisna bir devre için ölümcül olur. Bileşenlerin yaşam döngüsü yöntemlerindeki hatalarla başa çıkabilmek için hata işleme mantığı ekleyin.
Aşağıdaki örnekte OnParametersSetAsync bir ürünü almak için bir yöntemi çağırır:
-
ProductRepository.GetProductByIdAsync
yönteminde oluşan bir özel durum, birtry-catch
deyimi tarafından ele alınır. -
catch
Blok yürütülürken:-
loadFailed
olarak ayarlanırtrue
ve kullanıcıya bir hata iletisi görüntülemek için kullanılır. - Hata günlüğe kaydedilir.
-
@page "/product-details/{ProductId:int?}"
@inject ILogger<ProductDetails> Logger
@inject IProductRepository Product
<PageTitle>Product Details</PageTitle>
<h1>Product Details Example</h1>
@if (details != null)
{
<h2>@details.ProductName</h2>
<p>
@details.Description
<a href="@details.Url">Company Link</a>
</p>
}
else if (loadFailed)
{
<h1>Sorry, we could not load this product due to an error.</h1>
}
else
{
<h1>Loading...</h1>
}
@code {
private ProductDetail? details;
private bool loadFailed;
[Parameter]
public int ProductId { get; set; }
protected override async Task OnParametersSetAsync()
{
try
{
loadFailed = false;
// Reset details to null to display the loading indicator
details = null;
details = await Product.GetProductByIdAsync(ProductId);
}
catch (Exception ex)
{
loadFailed = true;
Logger.LogWarning(ex, "Failed to load product {ProductId}", ProductId);
}
}
public class ProductDetail
{
public string? ProductName { get; set; }
public string? Description { get; set; }
public string? Url { get; set; }
}
/*
* Register the service in Program.cs:
* using static BlazorSample.Components.Pages.ProductDetails;
* builder.Services.AddScoped<IProductRepository, ProductRepository>();
*/
public interface IProductRepository
{
public Task<ProductDetail> GetProductByIdAsync(int id);
}
public class ProductRepository : IProductRepository
{
public Task<ProductDetail> GetProductByIdAsync(int id)
{
return Task.FromResult(
new ProductDetail()
{
ProductName = "Flowbee ",
Description = "The Revolutionary Haircutting System You've Come to Love!",
Url = "https://flowbee.com/"
});
}
}
}
@page "/product-details/{ProductId:int?}"
@inject ILogger<ProductDetails> Logger
@inject IProductRepository Product
<PageTitle>Product Details</PageTitle>
<h1>Product Details Example</h1>
@if (details != null)
{
<h2>@details.ProductName</h2>
<p>
@details.Description
<a href="@details.Url">Company Link</a>
</p>
}
else if (loadFailed)
{
<h1>Sorry, we could not load this product due to an error.</h1>
}
else
{
<h1>Loading...</h1>
}
@code {
private ProductDetail? details;
private bool loadFailed;
[Parameter]
public int ProductId { get; set; }
protected override async Task OnParametersSetAsync()
{
try
{
loadFailed = false;
// Reset details to null to display the loading indicator
details = null;
details = await Product.GetProductByIdAsync(ProductId);
}
catch (Exception ex)
{
loadFailed = true;
Logger.LogWarning(ex, "Failed to load product {ProductId}", ProductId);
}
}
public class ProductDetail
{
public string? ProductName { get; set; }
public string? Description { get; set; }
public string? Url { get; set; }
}
/*
* Register the service in Program.cs:
* using static BlazorSample.Components.Pages.ProductDetails;
* builder.Services.AddScoped<IProductRepository, ProductRepository>();
*/
public interface IProductRepository
{
public Task<ProductDetail> GetProductByIdAsync(int id);
}
public class ProductRepository : IProductRepository
{
public Task<ProductDetail> GetProductByIdAsync(int id)
{
return Task.FromResult(
new ProductDetail()
{
ProductName = "Flowbee ",
Description = "The Revolutionary Haircutting System You've Come to Love!",
Url = "https://flowbee.com/"
});
}
}
}
@page "/product-details/{ProductId:int}"
@using Microsoft.Extensions.Logging
@inject ILogger<ProductDetails> Logger
@inject IProductRepository ProductRepository
@if (details != null)
{
<h1>@details.ProductName</h1>
<p>@details.Description</p>
}
else if (loadFailed)
{
<h1>Sorry, we could not load this product due to an error.</h1>
}
else
{
<h1>Loading...</h1>
}
@code {
private ProductDetail? details;
private bool loadFailed;
[Parameter]
public int ProductId { get; set; }
protected override async Task OnParametersSetAsync()
{
try
{
loadFailed = false;
// Reset details to null to display the loading indicator
details = null;
details = await ProductRepository.GetProductByIdAsync(ProductId);
}
catch (Exception ex)
{
loadFailed = true;
Logger.LogWarning(ex, "Failed to load product {ProductId}", ProductId);
}
}
public class ProductDetail
{
public string? ProductName { get; set; }
public string? Description { get; set; }
}
public interface IProductRepository
{
public Task<ProductDetail> GetProductByIdAsync(int id);
}
}
@page "/product-details/{ProductId:int}"
@using Microsoft.Extensions.Logging
@inject ILogger<ProductDetails> Logger
@inject IProductRepository ProductRepository
@if (details != null)
{
<h1>@details.ProductName</h1>
<p>@details.Description</p>
}
else if (loadFailed)
{
<h1>Sorry, we could not load this product due to an error.</h1>
}
else
{
<h1>Loading...</h1>
}
@code {
private ProductDetail? details;
private bool loadFailed;
[Parameter]
public int ProductId { get; set; }
protected override async Task OnParametersSetAsync()
{
try
{
loadFailed = false;
// Reset details to null to display the loading indicator
details = null;
details = await ProductRepository.GetProductByIdAsync(ProductId);
}
catch (Exception ex)
{
loadFailed = true;
Logger.LogWarning(ex, "Failed to load product {ProductId}", ProductId);
}
}
public class ProductDetail
{
public string? ProductName { get; set; }
public string? Description { get; set; }
}
public interface IProductRepository
{
public Task<ProductDetail> GetProductByIdAsync(int id);
}
}
@page "/product-details/{ProductId:int}"
@using Microsoft.Extensions.Logging
@inject ILogger<ProductDetails> Logger
@inject IProductRepository ProductRepository
@if (details != null)
{
<h1>@details.ProductName</h1>
<p>@details.Description</p>
}
else if (loadFailed)
{
<h1>Sorry, we could not load this product due to an error.</h1>
}
else
{
<h1>Loading...</h1>
}
@code {
private ProductDetail details;
private bool loadFailed;
[Parameter]
public int ProductId { get; set; }
protected override async Task OnParametersSetAsync()
{
try
{
loadFailed = false;
// Reset details to null to display the loading indicator
details = null;
details = await ProductRepository.GetProductByIdAsync(ProductId);
}
catch (Exception ex)
{
loadFailed = true;
Logger.LogWarning(ex, "Failed to load product {ProductId}", ProductId);
}
}
public class ProductDetail
{
public string ProductName { get; set; }
public string Description { get; set; }
}
public interface IProductRepository
{
public Task<ProductDetail> GetProductByIdAsync(int id);
}
}
@page "/product-details/{ProductId:int}"
@using Microsoft.Extensions.Logging
@inject ILogger<ProductDetails> Logger
@inject IProductRepository ProductRepository
@if (details != null)
{
<h1>@details.ProductName</h1>
<p>@details.Description</p>
}
else if (loadFailed)
{
<h1>Sorry, we could not load this product due to an error.</h1>
}
else
{
<h1>Loading...</h1>
}
@code {
private ProductDetail details;
private bool loadFailed;
[Parameter]
public int ProductId { get; set; }
protected override async Task OnParametersSetAsync()
{
try
{
loadFailed = false;
// Reset details to null to display the loading indicator
details = null;
details = await ProductRepository.GetProductByIdAsync(ProductId);
}
catch (Exception ex)
{
loadFailed = true;
Logger.LogWarning(ex, "Failed to load product {ProductId}", ProductId);
}
}
public class ProductDetail
{
public string ProductName { get; set; }
public string Description { get; set; }
}
public interface IProductRepository
{
public Task<ProductDetail> GetProductByIdAsync(int id);
}
}
İşleme mantığı
Bir Razor bileşen dosyasındaki (.razor
) bildirim temelli işaretleme, adlı BuildRenderTreebir C# yönteminde derlenmiştir. Bir bileşen işlendiğinde, BuildRenderTree işlenen bileşenin öğelerini, metnini ve alt bileşenlerini açıklayan bir veri yapısı yürütür ve oluşturur.
İşleme mantığı bir istisna fırlatabilir. Bu senaryonun bir örneği, @someObject.PropertyName
değerlendirildiğinde ancak @someObject
null
olduğunda oluşur. Bir devre üzerinde çalışan Blazor uygulamalar için, işleme mantığı tarafından oluşturulan işlenmeyen bir özel durum, uygulamanın devresi için öldürücü etki yapar.
Rendere mantığındaki bir NullReferenceException sorununu önlemek için, üyelerine erişmeden önce bir null
nesneyi denetleyin. Aşağıdaki örnekte, person.Address
null
ise person.Address
özelliklere erişilmez:
@if (person.Address != null)
{
<div>@person.Address.Line1</div>
<div>@person.Address.Line2</div>
<div>@person.Address.City</div>
<div>@person.Address.Country</div>
}
Yukarıdaki kod bunun person
olmadığını null
varsayar. Genellikle kodun yapısı, bileşenin işlendiği sırada bir nesnenin var olduğunu garanti eder. Bu gibi durumlarda, işleme mantığında null
kontrol etmek gerekli değildir. Önceki örnekte, person
bileşen örneği oluşturulduğunda oluşturulduğu için, person
'ün varlığı garanti edilebilir; bu, aşağıdaki örnekte gösterilmektedir.
@code {
private Person person = new();
...
}
Olay işleyicileri
İstemci tarafı kodu, aşağıdakiler kullanılarak olay işleyicileri oluşturulduğunda C# kodunun çağrılarını tetikler:
@onclick
@onchange
- Diğer
@on...
öznitelikler @bind
Olay işleyici kodu bu senaryolarda işlenmeyen bir özel durum oluşturabilir.
Uygulama dış nedenlerle başarısız olabilecek kodu çağırırsa, hata işleme ve loglama özelliğine sahip bir try-catch
deyimi kullanarak hataları yakalayın.
Bir olay işleyicisi, geliştirici kodu tarafından yakalanamayan ve işlenemeyen bir istisna fırlatırsa (örneğin, veritabanı sorgusu başarısız olursa):
- Çerçeve özel durumu günlüğe kaydeder.
- Bir devre üzerinden çalışan bir Blazor uygulamada, istisna uygulamanın devresi için ölümcül olur.
Bileşen bertarafı
Kullanıcı başka bir sayfaya gitmesinden dolayı bir bileşen kullanıcı arabiriminden kaldırılabilir. Uygulayan System.IDisposable bir bileşen kullanıcı arabiriminden kaldırıldığında, çerçeve bileşenin Dispose yöntemini çağırır.
Bileşenin Dispose
yöntemi bir devre üzerinde çalışan bir Blazor uygulamada işlenmeyen bir özel durum fırlatırsa, bu özel durum uygulamanın devresi için ölümcül olur.
Atma mantığı özel durumlar oluşturabilecekse, uygulamanın hata işleme ve günlüğe kaydetme ile bir try-catch
deyimi kullanarak özel durumları yakalaması gerekir.
Bileşen elden çıkarma hakkında daha fazla bilgi için bkz. ASP.NET Core Razor bileşen elden çıkarma.
JavaScript ile birlikte çalışma
IJSRuntime, Blazor çerçevesi tarafından kaydedilir. IJSRuntime.InvokeAsync .NET kodunun kullanıcının tarayıcısında JavaScript (JS) çalışma zamanına zaman uyumsuz çağrılar yapmasına izin verir.
aşağıdaki koşullar ile InvokeAsynchata işleme için geçerlidir:
- Bir InvokeAsync çağrısı eşzamanlı olarak başarısız olursa, bir .NET özel durumu oluşur. InvokeAsync çağrısı, örneğin sağlanan bağımsız değişkenler serileştirilemediğinden başarısız olabilir. Geliştirici kodu özel durumu yakalamalıdır. Bir olay işleyicisindeki veya bileşen yaşam döngüsü yöntemindeki uygulama kodu, bir devre üzerinde çalışan bir Blazor uygulamada bir özel durumu işlemezse, ortaya çıkan özel durum uygulamanın devresi için ölümcül olur.
-
InvokeAsync çağrısı zaman uyumsuz olarak başarısız olursa, .NET Task başarısız olur.
InvokeAsync çağrısı, örneğin, JS taraf kodu bir istisna fırlatabileceğinden veya
rejected
olarak tamamlanmış birPromise
döndürdüğünden başarısız olabilir. Geliştirici kodu özel durumu yakalamalıdır.await
işlecini kullanıyorsanız, yöntem çağrısını hata yönetimi ve log tutma içeren birtry-catch
deyimle sarmalamayı düşünün. Aksi takdirde, bir bağlantı hattı üzerinden çalışan bir Blazor uygulamada başarısız olan kod, uygulamanın bağlantı hattı için ölümcül olan işlenmemiş bir özel durumla sonuçlanır. - Çağrısının InvokeAsync belli bir süre içinde tamamlanması gerekir, aksi halde arama zaman aşımına uğramalıdır. Varsayılan zaman aşımı süresi bir dakikadır. Zaman aşımı, kodu ağ bağlantısı kaybına veya hiçbir zaman tamamlama mesajı göndermeyen JS koduna karşı korur. Arama zaman aşımına uğrarsa, sonuç System.Threading.Tasks bir OperationCanceledException ile başarısız olur. İstisnayı günlüğe kaydederek yakalayın ve işleyin.
Benzer şekilde,
- Bir devre üzerinde çalışan bir Blazor uygulamada, özel durum uygulamanın devresi için ölümcül olarak değerlendirilmez.
-
JS tarafındaki
Promise
reddedildi.
.NET tarafında veya JS yöntem çağrısının tarafında hata işleme kodunu kullanma seçeneğiniz vardır.
Daha fazla bilgi için aşağıdaki makaleleri inceleyin:
- ASP.NET Core Blazor'da .NET yöntemlerinden JavaScript işlevlerini çağırma
- ASP.NET Core Blazor'da JavaScript işlevlerinden .NET yöntemlerini çağırma
Önceden Renderleme
Razor bileşenleri varsayılan olarak önceden oluşturulur, böylece işlenen HTML işaretlemeleri kullanıcının ilk HTTP isteğinin bir parçası olarak döndürülür.
Devre üzerinden çalışan bir Blazor uygulamada, ön kayıt şu şekilde çalışır:
- Aynı sayfanın parçası olan önceden oluşturulmuş tüm bileşenler için yeni bir bağlantı hattı oluşturma.
- İlk HTML oluşturuluyor.
- Kullanıcının tarayıcısı aynı sunucuya yeniden bağlantı kurana kadar devreyi
disconnected
olarak ele alın. Bağlantı kurulduğunda, bağlantı hattındaki etkileşim sürdürülür ve bileşenlerin HTML işaretlemesi güncelleştirilir.
Önceden oluşturulmuş istemci tarafı bileşenleri için, ön kayıt şu şekilde çalışır:
- Aynı sayfanın parçası olan önceden oluşturulmuş tüm bileşenler için sunucuda ilk HTML oluşturuluyor.
- Tarayıcı, uygulamanın derlenmiş kodunu ve .NET çalışma zamanını (henüz yüklenmemişse) arka plana yükledikten sonra bileşeni istemcide etkileşimli hale getirme.
Bir bileşen, örneğin bir yaşam döngüsü yöntemi veya işleme mantığı sırasında ön kayıt sırasında işlenmeyen bir özel durum oluşturursa:
- Bir devre üzerinde çalışan bir Blazor uygulamada, özel durum devre için ölümcüldür. Önceden oluşturulmuş istemci tarafı bileşenleri için özel durum, bileşenin işlenmesini engeller.
- Özel durum çağrısı yığınından ComponentTagHelperoluşturulur.
Prerendering başarısız olduğunda normal koşullarda, çalışan bir bileşen işlenemediğinden bileşeni derlemeye ve işlemeye devam etmek mantıklı değildir.
Ön kayıt sırasında oluşabilecek hataları tolere etmek için hata işleme mantığı özel durumlar oluşturabilecek bir bileşenin içine yerleştirilmelidir. Hata işleme ve günlüğe kaydetme ile ifadeleri try-catch
kullanın.
try-catch
deyimi yerine ComponentTagHelper'yi sarmalamak, hata işleme mantığını ComponentTagHelper tarafından işlenen bileşene yerleştirin.
Gelişmiş senaryolar
Özyinelemeli işleme
Bileşenler özyinelemeli olarak iç içe yerleştirilebilir. Bu, özyinelemeli veri yapılarını temsil etmek için kullanışlıdır. Örneğin, bir TreeNode
bileşen düğümün alt öğelerinin her biri için daha fazla TreeNode
bileşen işleyebilir.
Özyinelemeli işlem yaparken, sonsuz özyinelemeye yol açan tekniklerden kaçınılmalıdır.
- Döngü içeren bir veri yapısını yinelemeli olarak işlemeyin. Örneğin, alt öğeleri kendisini içeren bir ağaç düğümü oluşturmayın.
- Döngü içeren bir düzen zinciri oluşturmayın. Örneğin, kendi kendisinin düzeni olan bir tasarım oluşturmayın.
- Son kullanıcının kötü amaçlı veri girişi veya JavaScript birlikte çalışma çağrıları aracılığıyla özyineleme sabitlerini (kuralları) ihlal etmelerine izin verme.
İşleme sırasında sonsuz döngüler:
- İşleme işleminin sonsuza kadar devam etmesine neden olur.
- Sonlandırılmamış döngü oluşturmaya eşdeğerdir.
Bu senaryolarda Blazor başarısız olur ve genellikle şunları yapmaya çalışır:
- İşletim sisteminin izin verdiği kadar CPU süresini süresiz olarak tüketin.
- Sınırsız miktarda bellek kullanın. Sınırsız bellek kullanmak, sonlandırılmamış bir döngünün her yinelemedeki bir koleksiyona girişler eklediği senaryoya eşdeğerdir.
Sonsuz özyineleme desenlerini önlemek için özyinelemeli işleme kodunun uygun durdurma koşulları içerdiğinden emin olun.
Özel görüntüleme ağacı mantığı
Razor bileşenlerin çoğu, Razor bileşen dosyaları olarak .razor
uygulanır ve çerçeve tarafından, kendi çıkışlarını işlemek üzere RenderTreeBuilder üzerinde çalışan mantığı üretmek için derlenir. Ancak, bir geliştirici C# yordam kodunu kullanarak mantığı manuel olarak uygulayabilir RenderTreeBuilder. Daha fazla bilgi için, ASP.NET Core Blazor gelişmiş senaryoları (işleme ağacı oluşturma) bölümüne bakın.
Uyarı
El ile işleme ağacı oluşturucu mantığının kullanılması gelişmiş ve güvenli olmayan bir senaryo olarak kabul edilir, genel bileşen geliştirme için önerilmez.
Kod yazılırsa RenderTreeBuilder geliştiricinin kodun doğruluğunu garanti etmesi gerekir. Örneğin, geliştirici şunları sağlamalıdır:
- OpenElement ve CloseElement çağrıları doğru şekilde dengelenir.
- Öznitelikler yalnızca doğru yerlere eklenir.
Yanlış el ile işleme ağacı oluşturucu mantığı, belirsiz rastgele davranışlara neden olabilir; bu, kilitlenmelere, uygulamanın veya sunucunun yanıt vermeyi durdurmasına ve güvenlik açıklarına yol açabilir.
Render ağacı oluşturma mantığını, elle derleme kodu veya Microsoft Ara Dil (MSIL) yönergeleri yazmakla aynı karmaşıklık ve tehlike düzeyinde değerlendirin.
Ek kaynaklar
- Bir bileşenin Razor yaşam döngüsü dışında yakalanan özel durumları işleme
- ASP.NET Core Blazor loglama
- ASP.NET Core'daki hataları işleme†
- ASP.NET Core ile web API'leri oluşturma
Örnekler GitHub deposu ( () nasıl indirilir )
†İstemci tarafı Blazor uygulamalarının günlüğe kaydetme için kullandığı arka uç ASP.NET Core web API'lerine uygulanır.
ASP.NET Core