Aracılığıyla paylaş


ASP.NET Core Blazor uygulamalarında hataları işleme

Not

Bu, bu makalenin en son sürümü değildir. Geçerli sürüm için bu makalenin .NET 9 sürümüne bakın.

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.

Önemli

Bu bilgiler, ticari olarak piyasaya sürülmeden önce önemli ölçüde değiştirilebilen bir yayın öncesi ürünle ilgilidir. Burada verilen bilgilerle ilgili olarak Microsoft açık veya zımni hiçbir garanti vermez.

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 şablonlarının tüm sürümleri, tarayıcılara hata kullanıcı arabiriminin içeriğini önbelleğe almamaları için özniteliği sinyalini kullanmaz, ancak belgelerin tüm sürümleri bu özniteliği uygular.

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.SignalRHata 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ı

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.

Kırmızı bir arka plana, 'Hata oluştu' metnine ve içinde ünlem işareti bulunan sarı bir uyarı simgesine sahip bir hata sınırı tarafından işlenen varsayılan hata kullanıcı arabirimi.

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öntemindeOnParameterSet, 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 ProcessErrorbileş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ğundaki ProcessError bileşenini CascadingParameter olarak belirleyin. Proje şablonunu temel alan Counter bir uygulamadaki örnek Blazor bileşene aşağıdaki ProcessError ö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. Örnek ProcessError bileşen yalnızca tek LogError 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ğıdaki Counter bileşen @code bloğu örneği basamaklı parametresini ProcessError 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ğunda ProcessError bileşenini CascadingParameter 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. Örnek ProcessError bileşen yalnızca tek LogError 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:

‡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:

†İ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, bir try-catch deyimi tarafından ele alınır.
  • catch Blok yürütülürken:
    • loadFailed olarak ayarlanır trueve 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 @someObjectnull 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.Addressnull 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ı nullvarsayar. 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ış bir Promise 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 bir try-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, kodu özniteliğiyle belirtilen .NET yöntemlerine çağrı başlatabilir. Bu .NET yöntemleri işlenmeyen bir özel durum oluşturursa:

  • 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:

Ö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

†İstemci tarafı Blazor uygulamalarının günlüğe kaydetme için kullandığı arka uç ASP.NET Core web API'lerine uygulanır.