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 8 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 8 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 8 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. Proje şablonlarının Blazor tüm sürümleri, tarayıcılara hata kullanıcı arabiriminin içeriğini önbelleğe almaması için sinyal vermek için özniteliğini kullanmazdata-nosnippet, ancak belgelerin tüm sürümleri Blazor özniteliğini uygular.

içinde Blazor Web App, bileşenindeki deneyimi özelleştirin MainLayout . Ortam Etiketi Yardımcısı (örneğin, <environment include="Production">...</environment>) bileşenlerde Razor desteklenmediğinden, aşağıdaki örnek farklı ortamlar IHostEnvironment için hata iletilerini yapılandırmak üzere ekler.

üst kısmında MainLayout.razor:

@inject IHostEnvironment HostEnvironment

Hata kullanıcı arabirimi işaretlemesini Blazor 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, dosyadaki deneyimi özelleştirin Pages/_Host.cshtml . 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, dosyadaki deneyimi özelleştirin Pages/_Layout.cshtml . 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, dosyadaki deneyimi özelleştirin Pages/_Host.cshtml . Aşağıdaki örnek, farklı ortamlar için hata iletilerini yapılandırmak için Ortam Etiketi Yardımcısı'nı kullanır.

Hata kullanıcı arabirimi işaretlemesini Blazor 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, dosyadaki deneyimi özelleştirin wwwroot/index.html :

<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 CSS sınıfının stilinin blazor-error-ui bulunması display: none nedeniyle normalde gizlenir. Bir hata oluştuğunda, çerçeve öğesine uygulanır display: block .

blazor-error-ui öğesi normalde sitenin klasördeki stil sayfasında CSS sınıfının stilinin blazor-error-ui bulunması display: none nedeniyle gizlenirwwwroot/css. Bir hata oluştuğunda, çerçeve öğesine uygulanır display: block .

Ayrıntılı bağlantı hattı hataları

Bu bölüm bir Blazor Web Appbağlantı hattı üzerinde çalışan 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 bağlantı hattı hata bilgileri, ayrıntılı hatalar etkinleştirilerek istemcinin kullanımına sunulabiliyor.

CircuitOptions.DetailedErrors seçeneğini true olarak ayarlayın. Daha fazla bilgi ve örnek için bkz . ASP.NET Temel BlazorSignalR kılavuzu.

Ayarın CircuitOptions.DetailedErrors alternatifi, yapılandırma anahtarını true uygulamanın Development ortam ayarları dosyasında (appsettings.Development.json olarak ayarlamaktırDetailedErrors). Ayrıca, ayrıntılı SignalR günlük kaydı için sunucu tarafı günlüğünü (Microsoft.AspNetCore.SignalR) Hata Ayıklama veya İzleme olarak ayarlayınSignalR.

appsettings.Development.json:

{
  "DetailedErrors": true,
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information",
      "Microsoft.AspNetCore.SignalR": "Debug"
    }
  }
}

Yapılandırma DetailedErrors anahtarı, ortam sunucularındaStaging Development/veya yerel sisteminizde değeri olan ortam değişkenini true kullanmaya ASPNETCORE_DETAILEDERRORS da ayarlanabilir.true

Uyarı

Hata bilgilerini İnternet'te istemcilere ifşa etmekten her zaman kaçının; bu bir güvenlik riskidir.

Bileşen sunucu tarafı işleme için Razor ayrıntılı 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ı etkinleştirir:

builder.Services.AddRazorComponents(options => 
    options.DetailedErrors = builder.Environment.IsDevelopment());

Uyarı

Yalnızca ortamdaki ayrıntılı hataları Development 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, değerini tarafından IsDevelopmentdöndürülen değere DetailedErrors göre ayarlayarak bir güvenlik derecesi sağlar. Uygulama Development ortamdayken olarak DetailedErrors ayarlanır true. Ü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 çerçeve özel durum iletilerini işlemeyin veya kullanıcı arabiriminde izlemeleri yığınlamayın. Özel durum iletileri veya yığın izlemeleri işlenebilir:

  • 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 özel durumlar

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 durum bilgisi vardı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 tetiklenebilen geçerli olay işleme temsilcileri 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 durumları, oluştukları bağlantı hattı için önemli olarak 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, kilitlenen 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 işlemi 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 kullanıcı arabirimini işler.

Hata sınırı tanımlamak için, bir veya daha fazla bileşeni sarmak için bileşenini kullanın ErrorBoundary . 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>

Hata sınırının yalnızca statik MainLayout bir bileşene uygulandığı s'deBlazor Web App, 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 RenderFragment temsilci olduğundan, bileşene Body etkileşimli işleme modu uygulanamaz. Bileşenin MainLayout ve rest bileşenlerin bileşen hiyerarşisinin daha aşağısında etkileşime olanak tanımak için, uygulamanın genellikle App bileşen olan kök bileşenindeki ve Routes bileşen örneklerine HeadOutlet etkileşimli işleme modunu uygulayarak genel bir 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 hata oluştuğunda sınır etkinleştirilebilir, ancak 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ştirilebilir.
  • Hata sınırının yerleştirildiği bileşen etkileşimliyse, hata sınırı kaydırdığı etkileşimli bileşenler için etkinleştirilebilme özelliğine sahiptir.

Not

Bir uygulamanın istemci tarafı işlemesi (CSR) Blazor WebAssembly tamamen etkileşimli olduğundan, önceki önemli noktalar tek başına Blazor WebAssembly uygulamalarla ilgili değildir.

Ekli sayaç bileşeni tarafından oluşan bir özel durumun, etkileşimli işleme modunu benimseyen bileşendeki Home 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 "/"
@rendermode InteractiveServer

<PageTitle>Home</PageTitle>

<h1>Home</h1>

<ErrorBoundary>
    <EmbeddedCounter />
</ErrorBoundary>

Katıştırılmış sayaç bileşeni tarafından oluşan bir özel durumun bileşendeki Home 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 kullanıcı arabirimi hata sınırı tarafından işlenir.

Bileşen, ErrorBoundary hata içeriği için CSS sınıfını blazor-error-boundary kullanarak boş <div> bir öğeyi 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:

  • özelliğindeki hata sınırının bileşenlerini sarmalar ChildContent .
  • ErrorContent özelliğini hata içeriği olarak ayarlayın.

Aşağıdaki örnek bileşeni sarmalar EmbeddedCounter 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 öğesi olmadan özelliğinden ErrorContent işlenir. Bölme () veya paragraf<p> (<div>) öğesi gibi blok düzeyinde bir öğe, hata içeriği işaretlemesini sarmalayabilir, ancak gerekli değildir.

İsteğe bağlı olarak, hata verilerini almak için bağlamını ErrorContent (@context) kullanın:

<ErrorContent>
    @context.HelpLink
</ErrorContent>

bağlamı ErrorContent da adlandırabilir. Aşağıdaki örnekte bağlam olarak adlandırılır exception:

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

  • öznitelik yönergesi ErrorBoundary ile @ref bir başvuru yakalamak için bir alan 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();
    }
}

Kurtarma işleminin yalnızca hatayı yeniden oluşturan bir bileşeni yeniden oluşturduğu sonsuz döngüden kaçınmak için işleme mantığını çağırmayın Recover . Yalnızca şu durumlarda arama Recover :

  • Kullanıcı, bir yordamı yeniden denemek istediğini veya kullanıcı yeni bir bileşene gittiği zaman düğme seçme gibi bir kullanıcı arabirimi hareketi gerçekleştirir.
  • Yürütülen ek mantık da özel durumu temizler. Bileşen yeniden başlatıldığında hata yinelenmez.

Aşağıdaki örnek, kullanıcının bir düğmeyle özel durumdan kurtarması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;
}

Ayrıca geçersiz kılarak OnErrorAsyncözel işleme için alt sınıf ErrorBoundary oluşturabilirsiniz. Aşağıdaki örnek yalnızca hatayı günlüğe kaydeder, ancak istediğiniz hata işleme kodunu uygulayabilirsiniz. Kodunuz zaman uyumsuz bir CompletedTask görev bekliyorsa döndüren satırı 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 (, veya ) benimseyen , Blazor WebAssemblyve Blazor Web Apps için geçerlidirBlazor Server.InteractiveAutoInteractiveWebAssemblyInteractiveServer Yaklaşım, işleme modu sınırları boyunca veya statik SSR'yi benimseyen bileşenlerle çalışmayan bir CascadingValue/CascadingParameteröğesine bağlı olduğundan, yaklaşım sayfa başına/bileşen işleme modlarını veya statik sunucu tarafı işlemeyi (statik SSR) benimseyenlerle çalışmaz.Blazor Web App

Hata sınırlarını (ErrorBoundary) kullanmanın bir alternatifi, özel bir hata bileşenini alt bileşenlere geçirmektir.CascadingValue 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 Appiçinde kullanırken, bileşeni açın Routes ve bileşeni (<Router>...</Router>) bileşenle sarmalar Router ProcessError. Bu, bileşenin, bileşenin ProcessError olarak alındığı uygulamanın herhangi bir CascadingParameterbileşenine art arda inmesine ProcessError izin verir.

Routes.razor içinde:

<ProcessError>
    <Router ...>
        ...
    </Router>
</ProcessError>

Bir veya uygulamasında bu yaklaşımı Blazor Server kullanırken, bileşeni açınApp, bileşeni (<Router>...</Router>) bileşenle sarmalar Router ProcessError.Blazor WebAssembly Bu, bileşenin, bileşenin ProcessError olarak alındığı uygulamanın herhangi bir CascadingParameterbileşenine art arda inmesine ProcessError izin verir.

App.razor içinde:

<ProcessError>
    <Router ...>
        ...
    </Router>
</ProcessError>

Bir bileşendeki hataları işlemek için:

  • Bileşeni blokta @code olarak CascadingParameter belirleyinProcessError. Proje şablonunu temel alan Blazor bir uygulamadaki örnek Counter 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);
            }
        }
    }
    

Günlüğe kaydedilen hata:

fail: {COMPONENT NAMESPACE}.ProcessError[0]
ProcessError.LogError: System.InvalidOperationException Message: Current count is over five!

LogError Yöntem, ö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 yöntemin LogError sonunda çağrısı StateHasChanged 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 bağlantı hattı için önemli 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 alt bileşenlere geçirir CascadingValue . 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şendeApp, bileşeni bileşenle birlikte sarmalar ProcessError Router. Bu, bileşenin, bileşenin ProcessError olarak alındığı uygulamanın herhangi bir CascadingParameterbileşenine art arda inmesine ProcessError izin verir.

App.razor:

<ProcessError>
    <Router ...>
        ...
    </Router>
</ProcessError>

Bir bileşendeki hataları işlemek için:

  • ProcessError Bileşeni bloğunda @code olarak CascadingParameter 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);
    }
    

Yukarıdaki örnek ProcessError bileşeni ve LogError yöntemi kullanarak tarayıcının geliştirici araçları konsolu kapana kısılmış, günlüğe 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öntem, ö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 yöntemin LogError sonunda çağrısı StateHasChanged yapı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 bağlantı hattı için önemlidir. Daha fazla bilgi için, devrenin işlenmeyen özel durumlara nasıl tepki vermesine ilişkin bölüme bakın.

Kalıcı sağlayıcıyla hataları günlüğe kaydetme

İşlenmeyen bir özel durum oluşursa, özel durum hizmet kapsayıcısında yapılandırılan örneklere ILogger kaydedilir. Blazor uygulamalar, Konsol Günlüğü Sağlayıcısı ile 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 Azure Uygulaması lication Insights (Azure İzleyici) gibi bir Uygulama Performansı Yönetimi (APM) hizmeti kullanabilir.

Not

İstemci tarafı uygulamalarını desteklemek için yerel Application Insights özellikleri ve Google Analytics için yerel Blazor ç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 kaydetme olayı olarak değerlendirilmemelidir.

Daha fazla bilgi için aşağıdaki makaleleri inceleyin:

‡için web API arka uç uygulamaları olan sunucu tarafı Blazor uygulamalar ve diğer sunucu tarafı ASP.NET Core uygulamaları için Blazorgeçerlidir. İstemci tarafı uygulamaları, istemcideki hata bilgilerini yakalayıp bir web API'sine gönderebilir ve bu da hata bilgilerini kalıcı bir günlük sağlayıcısına günlüğe kaydeder.

İşlenmeyen bir özel durum oluşursa, özel durum hizmet kapsayıcısında yapılandırılan örneklere ILogger kaydedilir. Blazor uygulamalar, Konsol Günlüğü Sağlayıcısı ile konsol çıkışı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'si uygulaması istemcilerden aldığı hata bilgilerini kaydetmek için Azure Uygulaması lication 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'sinde bilinmeyen ProductId bir hatanın bulunduğu bir hatayı günlüğe kaydetmeyin. Tüm hatalar günlüğe kaydetme olayı olarak değerlendirilmemelidir.

Daha fazla bilgi için aşağıdaki makaleleri inceleyin:

†İstek tarafı uygulamaları ve Google Analytics için yerel Blazor çerçeve desteğini desteklemek için †Native Application Insights özellikleri, 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.

‡Uygulamalar için web API arka uç uygulamaları olan sunucu tarafı ASP.NET Core uygulamaları için Blazor geçerlidir. İstemci tarafı uygulamalar yakalanıp hata bilgilerini bir web API'sine gönderir ve hata bilgilerini kalıcı bir günlük 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şturma

Bir bileşenin örneğini oluşturduğunda Blazor :

  • Bileşenin oluşturucusunun çağrılır.
  • yönergesi veya özniteliği aracılığıyla @inject bileşenin oluşturucusunun sağladığı DI hizmetlerinin [Inject] 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 hata işleme ve günlüğe kaydetme ile bir try-catch deyimi kullanarak özel durumları yakalamalıdır.

Yaşam döngüsü yöntemleri

Bir bileşenin ömrü boyunca yaşam Blazor döngüsü yöntemlerini çağırır. Herhangi bir yaşam döngüsü yöntemi zaman uyumlu veya zaman uyumsuz bir özel durum oluşturursa, özel durum bir bağlantı hattı için önemli 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:

  • yönteminde ProductRepository.GetProductByIdAsync oluşan bir özel durum bir try-catch deyimi tarafından işlenir.
  • 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ığı özel durum oluşturabilir. Bu senaryonun bir örneği, değerlendirildiğinde @someObject.PropertyName ancak @someObject olduğunda nulloluşur. Bir devre üzerinde çalışan uygulamalar için Blazor , işleme mantığı tarafından oluşan işlenmeyen bir özel durum, uygulamanın devresinde önemli olur.

İşleme mantığını önlemek NullReferenceException için, üyelerine erişmeden önce bir null nesneyi denetleyin. Aşağıdaki örnekte ise person.Address özelliklere person.Address nullerişilenmez:

@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ığını denetlemek null gerekmez. Önceki örnekte, person aşağıdaki örnekte gösterildiği gibi bileşen örneği oluşturulurken oluşturulduğu için var person olacağı garanti edilebilir:

@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 günlüğe kaydetme özelliğine sahip bir try-catch deyimi kullanarak özel durumları yakalayın.

Bir olay işleyicisi, geliştirici kodu tarafından tuzağa düşürülmeyen ve işlenmeyen bir özel durum oluşturursa (örneğin, veritabanı sorgusu başarısız oluyorsa):

  • Çerçeve özel durumu günlüğe kaydeder.
  • Bir bağlantı hattı üzerinden çalışan bir Blazor uygulamada, özel durum uygulamanın bağlantı hattı için önemli olur.

Bileşen elden çıkarma

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 bağlantı hattı üzerinde çalışan bir Blazor uygulamada işlenmeyen bir özel durum oluşturursa, özel durum uygulamanın bağlantı hattı için önemli 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şenin elden çıkarılması hakkında daha fazla bilgi için bkz . ASP.NET Core Razor bileşen yaşam döngüsü.

JavaScript ile birlikte çalışma

IJSRuntime , çerçeve tarafından Blazor 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:

  • Çağrısı InvokeAsync zaman uyumlu olarak başarısız olursa bir .NET özel durumu oluşur. InvokeAsync Örneğin, sağlanan bağımsız değişkenler serileştirilemediğinden çağrısı 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 bağlantı hattı üzerinde çalışan bir Blazor uygulamada özel durumu işlemezse, sonuçta elde edilen özel durum uygulamanın devresinde önemli olur.
  • Çağrısı InvokeAsync zaman uyumsuz olarak başarısız olursa , .NET Task başarısız olur. InvokeAsync Örneğin, -side kodu bir özel durum oluşturacağından veya olarak rejectedtamamlanmış bir Promise döndürdüğünden JSçağrısı başarısız olabilir. Geliştirici kodu özel durumu yakalamalıdır. işlecini await kullanıyorsanız, yöntem çağrısını hata işleme ve günlüğe kaydetme ile bir try-catch deyimde sarmalamanız gerekir. Aksi takdirde, bir bağlantı hattı üzerinden çalışan bir Blazor uygulamada başarısız olan kod, uygulamanın bağlantı hattında önemli olan işlenmemiş bir özel durumla sonuçlanabilir.
  • çağrısının InvokeAsync belirli bir süre içinde tamamlanması gerekir, aksi halde arama zaman aşımına ulmalıdır. Varsayılan zaman aşımı süresi bir dakikadır. Zaman aşımı, kodu hiçbir zaman tamamlama iletisi göndermeden ağ bağlantısı veya JS kod kaybına karşı korur. Arama zaman aşımına ularsa, sonuç System.Threading.Tasks bir OperationCanceledExceptionile başarısız olur. Özel durumu günlüğe kaydetme ile yakalayın ve işleyin.

Benzer şekilde, JS kod özniteliği tarafından belirtilen .NET yöntemlerine [JSInvokable] çağrı başlatabilir. Bu .NET yöntemleri işlenmeyen bir özel durum oluşturursa:

  • Bir bağlantı hattı üzerinden çalışan bir Blazor uygulamada, özel durum uygulamanın bağlantı hattı için önemli olarak kabul edilir.
  • JS-side Promise reddedilir.

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

Ön Kayıt

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 SignalR kadar bağlantı hattını olarak disconnected ele alır. 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 bağlantı hattı üzerinde çalışan bir Blazor uygulamada, özel durum devre için önemlidir. Ö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 deyimleri kullanın try-catch . deyimini ComponentTagHelper sarmalamak try-catch yerine hata işleme mantığını tarafından işlenen bileşene ComponentTagHelperyerleş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 olarak işlenirken, sonsuz özyinelemeyle sonuçlayan kodlama desenlerinden kaçının:

  • 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, düzeni kendisinde olan bir düzen 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 başarısız Blazor 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 işleme ağacı mantığı

Çoğu Razor bileşen bileşen dosyası (.razor) olarak Razor uygulanır ve kendi çıkışını işlemek için üzerinde RenderTreeBuilder çalışan mantık üretmek için çerçeve tarafından derlenir. Ancak, bir geliştirici yordam C# kodunu kullanarak mantığını el ile uygulayabilir RenderTreeBuilder . Daha fazla bilgi için bkz . ASP.NET Çekirdek Blazor gelişmiş senaryoları (işleme ağacı oluşturma).

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:

  • ve CloseElement çağrıları OpenElement doğru şekilde dengelenir.
  • Öznitelikler yalnızca doğru yerlere eklenir.

Yanlış el ile işleme ağacı oluşturucu mantığı kilitlenmeler, uygulama veya sunucunun yanıt vermeyi durdurması ve güvenlik açıkları gibi rastgele tanımsız davranışlara neden olabilir.

El ile işleme ağacı oluşturucusu mantığını aynı karmaşıklık düzeyinde ve derleme kodu veya Microsoft Ara Dil (MSIL) yönergelerini el ile yazmayla aynı tehlike düzeyinde kullanmayı göz önünde bulundurun.

Ek kaynaklar

†Uygulama tarafı Blazor uygulamalarının günlüğe kaydetme için kullandığı arka uç ASP.NET Core web API'sine uygulama.