Aracılığıyla paylaş


ASP.NET Core Blazor JavaScript birlikte çalışabilirlik (JS interop)

Not çizelgesi

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.

Blazor uygulaması JavaScript (JS) işlevlerini .NET yöntemlerinden ve .NET yöntemlerini JS işlevlerinden çağırabilir. Bu senaryolar JavaScript birlikte çalışabilirliği (JS interop) olarak adlandırılır.

Aşağıdaki makalelerde daha fazla JS interop rehberliği sağlanır:

Not çizelgesi

JavaScript birlikte çalışma API'si [JSImport]/[JSExport] , .NET 7 veya sonraki sürümlerde ASP.NET Core'daki istemci tarafı bileşenleri için kullanılabilir.

Daha fazla bilgi için bkz: ASP.NET Core ile JavaScript JSImport/JSExport birlikte çalışma Blazor.

Güvenilmeyen verilerle etkileşimli sunucu bileşenleri için sıkıştırma

Varsayılan olarak etkin olan sıkıştırma ile güvenilmeyen kaynaklardan veri işleyen güvenli (kimliği doğrulanmış/yetkilendirilmiş) etkileşimli sunucu tarafı bileşenleri oluşturmaktan kaçının. Güvenilmeyen kaynaklar arasında yol parametreleri, sorgu dizeleri, birlikte çalışma verileri JS ve üçüncü taraf bir kullanıcının denetleyebileceği diğer veri kaynakları (veritabanları, dış hizmetler) bulunur. Daha fazla bilgi için bkz . ASP.NET Core BlazorSignalR kılavuzu ve ASP.NET Core Blazor etkileşimli sunucu tarafı işleme için tehdit azaltma kılavuzu.

JavaScript birlikte çalışabilirlik soyutlamaları ve özellikler paketi

@microsoft/dotnet-js-interop Paket (npmjs.com) (Microsoft.JSInterop NuGet paketi), .NET ile JavaScript (JS) kodu arasında birlikte çalışma için soyutlamalar ve özellikler sağlar. Başvuru kaynağı GitHub deposunda ( klasör)dotnet/aspnetcore/src/JSInterop. Daha fazla bilgi için GitHub deposunun README.md dosyasına bakın.

Not çizelgesi

.NET başvuru kaynağına yönelik belge bağlantıları genellikle deponun varsayılan dalını yükler ve bu dal .NET'in sonraki sürümü için geçerli geliştirmeyi temsil eder. Belirli bir sürümün etiketini seçmek için Dalları veya etiketleri değiştir menüsünü kullanın. Daha fazla bilgi için bkz. ASP.NET Core kaynak kodunun sürüm etiketini seçme (dotnet/AspNetCore.Docs #26205).

TypeScript'te interop betikleri yazmak için ek kaynaklar:

DOM ile etkileşim

Nesne JS ile etkileşimde olmadığında, yalnızca JavaScript (Blazor) kullanarak DOM'u değiştirin. Blazor DOM gösterimlerini korur ve DOM nesneleriyle doğrudan etkileşim kurar. Blazor tarafından işlenen öğe doğrudan JS kullanılarak veya JS Interop yoluyla dışarıdan değiştirilirse, DOM artık Blazor'ın iç gösterimini eşleştiremeyebilir ve bu da tanımsız bir davranışla sonuçlanabilir. Tanımsız davranış öğelerin veya işlevlerinin gösterimini etkileyebilir ama aynı zamanda uygulama veya sunucu için güvenlik risklerine de neden olabilir.

Bu rehber yalnızca kendi JS interop kodunuz için değil, aynı zamanda JS ve JS gibi üçüncü taraflarca sağlananlar da dahil olmak üzere uygulamanın kullandığı tüm kitaplıkları için geçerlidir.

Birkaç belge örneğinde, JS interop örneğin bir parçası olarak yalnızca tanıtım amacıyla bir öğeyi değiştirmek için kullanılmıştır. Böyle durumlarda metinde bir uyarı görüntülenir.

Daha fazla bilgi için bkz. ASP.NET Core Blazor'da .NET yöntemlerinden JavaScript işlevlerini çağırma.

İşlev türünde bir alana sahip JavaScript sınıfı

JavaScript'te işlev türünde bir alana sahip bir sınıf BlazorJS uyumluluğu tarafından desteklenmez. Sınıflarda Javascript işlevlerini kullanın.

Desteklenmiyor:GreetingHelpers.sayHello Aşağıdaki sınıfta işlev türü alanı olarak Blazor'ın JS interopu tarafından keşfedilmez ve C# kodundan yürütülemez:

export class GreetingHelpers {
  sayHello = function() {
    ...
  }
}

Desteklenir:GreetingHelpers.sayHello Aşağıdaki sınıfta işlev olarak desteklenir:

export class GreetingHelpers {
  sayHello() {
    ...
  }
}

Ok işlevleri de desteklenir:

export class GreetingHelpers {
  sayHello = () => {
    ...
  }
}

Satır içi olay işleyicilerinden kaçının

JavaScript işlevi doğrudan bir satır içi olay işleyicisinden çağrılabilir. Aşağıdaki örnekte, alertUser düğme kullanıcı tarafından seçildiğinde çağrılan bir JavaScript işlevidir:

<button onclick="alertUser">Click Me!</button>

Ancak, satır içi olay işleyicilerinin kullanımı JavaScript işlevlerini çağırmak için kötü bir tasarım seçeneğidir :

JavaScript'te addEventListener ile işleyicileri atayan yaklaşımlar kullanarak, satır içi olay işleyicilerinden kaçınmanızı öneririz, aşağıdaki örnek bunu göstermektedir.

AlertUser.razor.js:

export function alertUser() {
  alert('The button was selected!');
}

export function addHandlers() {
  const btn = document.getElementById("btn");
  btn.addEventListener("click", alertUser);
}

AlertUser.razor:

@page "/alert-user"
@implements IAsyncDisposable
@inject IJSRuntime JS

<h1>Alert User</h1>

<p>
    <button id="btn">Click Me!</button>
</p>

@code {
    private IJSObjectReference? module;

    protected async override Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            module = await JS.InvokeAsync<IJSObjectReference>("import",
                "./Components/Pages/AlertUser.razor.js");

            await module.InvokeVoidAsync("addHandlers");
        }
    }

    async ValueTask IAsyncDisposable.DisposeAsync()
    {
        if (module is not null)
        {
            try
            {
                await module.DisposeAsync();
            }
            catch (JSDisconnectedException)
            {
            }
        }
    }
}

Yukarıdaki örnekte, JSDisconnectedException bağlantı hattının kaybolması durumunda BlazorSignalR modülün imhası sırasında tuzağa düşürülecektir. Önceki kod bir Blazor WebAssembly uygulamada kullanılıyorsa, kaybedilecek bir bağlantı yoktur, bu nedenle SignalRtry- bloğunu kaldırabilir ve modülü (catch) atan satırı bırakabilirsiniz. Daha fazla bilgi için bkz. ASP.NET Core Blazor JavaScript birlikte çalışabilirliği (JSinterop).

Daha fazla bilgi edinmek için aşağıdaki kaynaklara bakın:

Zaman uyumsuz JavaScript çağrıları

JS birlikte çalışma çağrıları, yapılan kodun eşzamanlı veya eşzamanlı olmayan olmasına bakılmaksızın eşzamanlı olmayan şekilde gerçekleşir. Bileşenlerin sunucu tarafı ve istemci tarafı işleme modelleri arasında uyumlu olmasını sağlamak için çağrılar zaman uyumsuz hale getirilmiştir. Sunucu tarafı işlemeyi benimserken, JS birlikte çalışma çağrıları bir ağ bağlantısı üzerinden gönderildiği için eşzamansız olmalıdır. yalnızca istemci tarafı görselleştirmeyi benimseyen uygulamalar için zaman uyumlu JS birlikte çalışma çağrıları desteklenir.

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

Daha fazla bilgi için bkz. ASP.NET Core Blazor'da .NET yöntemlerinden JavaScript işlevlerini çağırma.

Nesne serileştirme

Blazor serileştirme için, aşağıdaki gereksinimler ve varsayılan davranışlarla System.Text.Json kullanır:

  • Türlerin varsayılan oluşturucusu olmalıdır, get/set erişimciler genel olmalıdır ve alanlar hiçbir zaman serileştirilmez.
  • Mevcut bileşen kitaplıklarının bozulmasını, performans ve güvenlik etkilerini, ayrıca güvenilirliğin azalmasını önlemek için genel varsayılan serileştirme özelleştirilemez.
  • .NET üye adlarını seri hale getirerek küçük harf JSON anahtar adları elde edebilirsiniz.
  • JSON, karışık büyük/küçük harfe izin veren C# nesneleri olarak JsonElement deserialize edilir. C# modelinin özelliklerine yapılan iç atama, JSON anahtar adları ile C# özelliği adları arasındaki büyük/küçük harf farklarına rağmen beklendiği gibi çalışır.
  • KeyValuePairgibi karmaşık çerçeve türleri, yayımlama IL Düzelticisi tarafından kırpılabilir ve JS birlikte çalışma veya JSON serileştirme/seri durumdan çıkarma için mevcut olmayabilir. IL Trimmer'ın kaldırdığı türler için özel türler oluşturmanızı öneririz.
  • Blazor C# kaynak oluşturma da dahil olmak üzere her zaman JSON serileştirme için yansımayı kullanır. Uygulamanın proje dosyasında JsonSerializerIsReflectionEnabledByDefault'yi false olarak ayarlamak, serileştirme denendiğinde hataya neden olur.

Özel serileştirme için JsonConverter API'si kullanılabilir. Mevcut veri türünde varsayılan serileştirmeyi geçersiz kılmak için özelliklere [JsonConverter] özniteliğiyle not eklenebilir.

Daha fazla bilgi için .NET belgelerinde aşağıdaki kaynaklara bakın:

Blazor, bayt dizilerinin Base64'e kodlanmasını/kodunun çözülmesini önleyen iyileştirilmiş bayt dizisi JS interop'u destekler. Uygulama özel serileştirme yapabilir ve sonuçta elde edilen baytları aktarabilir. Daha fazla bilgi için bkz. ASP.NET Core Blazor'da .NET yöntemlerinden JavaScript işlevlerini çağırma.

Yüksek hacimli .NET nesneleri hızla serileştirildiğinde ya da büyük .NET nesnelerinin veya birçok .NET nesnesinin serileştirilmesi gerektiğinde serileştirilmemiş BlazorJS interop'u destekler. Daha fazla bilgi için bkz. ASP.NET Core Blazor'da .NET yöntemlerinden JavaScript işlevlerini çağırma.

Bileşen imhası sırasında DOM temizleme görevleri

Bileşen elden çıkarılırken DOM temizleme görevleri için JS ilişkilendirme kodunu yürütmeyin. Bunun yerine, aşağıdaki nedenlerle istemcide JavaScript (MutationObserver) desenini kullanınJS:

  • Temizleme kodunuz Dispose{Async} içinde yürütüldüğünde bileşen DOM'dan kaldırılmış olabilir.
  • Sunucu tarafı işleme sırasında, Blazor render motoru, temizleme kodunuz Dispose{Async} içinde çalıştırıldığında çerçeve tarafından atılmış olabilir.

Desen, MutationObserver bir öğe DOM'dan kaldırıldığında bir işlevi çalıştırmanıza olanak tanır.

Aşağıdaki örnekte DOMCleanup bileşeni:

  • <div> ile bir idcleanupDiviçerir. <div> öğesi DOM'dan kaldırılır ve bileşen DOM'dan kaldırıldığında bileşenin DOM işaretlemesinin geri kalanıyla birlikte kaldırılır.
  • DOMCleanup dosyasından JSDOMCleanup.razor.js sınıfını yükler ve geri çağırmayı ayarlamak için createObserver işlevini çağırır.MutationObserver Bu görevler yaşam döngüsü yönteminde OnAfterRenderAsyncgerçekleştirilir.

DOMCleanup.razor:

@page "/dom-cleanup"
@implements IAsyncDisposable
@inject IJSRuntime JS

<h1>DOM Cleanup Example</h1>

<div id="cleanupDiv"></div>

@code {
    private IJSObjectReference? module;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            module = await JS.InvokeAsync<IJSObjectReference>(
                "import", "./Components/Pages/DOMCleanup.razor.js");

            await module.InvokeVoidAsync("DOMCleanup.createObserver");
        }
    }

    async ValueTask IAsyncDisposable.DisposeAsync()
    {
        if (module is not null)
        {
            try
            {
                await module.DisposeAsync();
            }
            catch (JSDisconnectedException)
            {
            }
        }
    }
}

Yukarıdaki örnekte, JSDisconnectedException bağlantı hattının kaybolması durumunda BlazorSignalR modülün imhası sırasında tuzağa düşürülecektir. Önceki kod bir Blazor WebAssembly uygulamada kullanılıyorsa, kaybedilecek bir bağlantı yoktur, bu nedenle SignalRtry- bloğunu kaldırabilir ve modülü (catch) atan satırı bırakabilirsiniz. Daha fazla bilgi için bkz. ASP.NET Core Blazor JavaScript birlikte çalışabilirliği (JSinterop).

Aşağıdaki örnekte, MutationObserver geri çağırma her DOM değişikliği gerçekleştiğinde çalıştırılır. if deyimi hedef öğenin cleanupDiv kaldırıldığını onayladığında, if (targetRemoved) { ... } temizleme kodunuzu yürütün. Temizleme kodunuz yürütüldükten sonra bellek sızıntısını önlemek için MutationObserver bağlantısının kesilip silinmesi önemlidir.

DOMCleanup.razor.js önceki DOMCleanup bileşenle yan yana yerleştirilir:

export class DOMCleanup {
  static observer;

  static createObserver() {
    const target = document.querySelector('#cleanupDiv');

    this.observer = new MutationObserver(function (mutations) {
      const targetRemoved = mutations.some(function (mutation) {
        const nodes = Array.from(mutation.removedNodes);
        return nodes.indexOf(target) !== -1;
      });

      if (targetRemoved) {
        // Cleanup resources here
        // ...

        // Disconnect and delete MutationObserver
        this.observer && this.observer.disconnect();
        delete this.observer;
      }
    });

    this.observer.observe(target.parentNode, { childList: true });
  }
}

window.DOMCleanup = DOMCleanup;

Önceki yaklaşımlar MutationObservertarget.parentNodeekler ve parentNode DOM'dan kaldırılana kadar çalışır. Bu, örneğin yeni bir sayfaya giderken sayfa bileşeninin tamamının DOM'dan kaldırılmasına neden olan yaygın bir senaryodur. Bu gibi durumlarda, sayfadaki değişiklikleri gözlemleyen alt bileşenler düzgün bir şekilde temizlenmez.

document.bodyyerine target.parentNodegözlemlemenin daha iyi bir hedef olduğunu varsaymayın. document.body gözlemlemenin performans üzerindeki etkileri vardır çünkü geri çağırma mantığı, öğenizle bir ilgisi olup olmadığına bakılmaksızın tüm DOM güncelleştirmeleri için yürütülür. Aşağıdaki yaklaşımlardan birini kullanın:

  • Gözlemlemek için uygun bir ata düğümü tanımlayabildiğiniz durumlarda, MutationObserver'ı onunla birlikte kullanın. İdeal olarak, bu ata, document.body yerine gözlemlemek istediğiniz değişikliklerle sınırlandırılmıştır.
  • MutationObserverkullanmak yerine bir özel öğesi ve disconnectedCallbackkullanmayı göz önünde bulundurun. DOM'da, DOM değişikliğine göre nerede bulunursa bulunsun, özel öğenizin bağlantısı kesildiğinde olay her zaman tetiklenir.

Devre olmadan JavaScript uyum çağrıları

Bu bölüm yalnızca sunucu tarafı uygulamalar için geçerlidir.

Bağlantı kesildikten sonra JS'nin Blazor devresiyle SignalR JavaScript birlikte çalışma çağrıları yapılamaz. Bir devre olmadığında, bileşenin atılması sırasında veya başka bir zamanda, aşağıdaki yöntem çağrıları başarısız olur ve devrenin bağlantısının kesildiğini belirten bir JSDisconnectedException iletisi kaydeder.

Özel durumu bir JSDisconnectedException ifadesinde yakalayarak, günlüğe kaydetmeyi veya özel bilgileri kaydetmeyi önleyin.

Aşağıdaki bileşen bertarafı örneği için:

  • Sunucu tarafı bileşeni IAsyncDisposable'yi gerçekleştirir.
  • module, IJSObjectReference modülü için bir JS'dir.
  • JSDisconnectedException yakalandı ancak günlüğe kaydedilmedi.
  • İsteğe bağlı olarak, istediğiniz günlük düzeyinde catch ifadesine özel bilgiler kaydedebilirsiniz. Aşağıdaki örnek, geliştiricinin bileşen elden çıkarma sırasında bağlantı hatlarının ne zaman veya nerede kesileceğiyle ilgilenmediği varsayıldığından özel bilgileri günlüğe kaydetmez.
async ValueTask IAsyncDisposable.DisposeAsync()
{
    try
    {
        if (module is not null)
        {
            await module.DisposeAsync();
        }
    }
    catch (JSDisconnectedException)
    {
    }
}

Sunucu tarafı JS uygulamasında bir devre kaybolduktan sonra kendi JS nesnelerinizi temizlemeniz veya istemcide başka Blazor bir kod yürütmeniz gerekiyorsa, istemcide MutationObserver içindeki JS desenini kullanın. Desen, MutationObserver bir öğe DOM'dan kaldırıldığında bir işlevi çalıştırmanıza olanak tanır.

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

Önbelleğe alınan JavaScript dosyaları

JavaScript (JS) dosyaları ve diğer statik varlıklar Developmentortamında geliştirme sırasında genel olarak istemcilerde önbelleğe alınmaz. Geliştirme sırasında, statik varlık istekleri Cache-Control başlığınıno-cache değeri veya sıfır (max-age) değeri olan 0 ile içerir.

Production ortamında üretim sırasında JS dosyaları genellikle istemciler tarafından önbelleğe alınır.

Tarayıcılarda istemci tarafı önbelleğini devre dışı bırakmak için geliştiriciler genellikle aşağıdaki yaklaşımlardan birini benimser:

  • Tarayıcıların geliştirici araçları konsolu açık olduğunda önbelleği devre dışı bırakma. Yönergeler, her tarayıcı bakımcısının geliştirici araçları belgelerinde bulunabilir:
  • Sunucudan Blazor dosyalarını yeniden yüklemek için JS uygulamasının herhangi bir web sayfasında el ile tarayıcı yenilemesi gerçekleştirin. ASP.NET Core'un HTTP Önbellek Ara Yazılımı, istemci tarafından gönderilen geçerli bir önbelleğe almama Cache-Control üst bilgisini her zaman kabul eder.

Daha fazla bilgi için bkz.

JavaScript birlikte çalışma çağrılarında boyut sınırları

Bu bölüm yalnızca sunucu tarafı uygulamalarındaki etkileşimli bileşenler için geçerlidir. İstemci tarafı bileşenleri için, framework JavaScript (JS) interop giriş ve çıkışlarının boyutuna bir sınır getirmez.

Sunucu tarafı uygulamalarındaki etkileşimli bileşenler için, JS istemciden sunucuya veri aktarımı yapan birlikte çalışma çağrılarının boyutu, hub yöntemleri için izin verilen en yüksek gelen SignalR ileti boyutuyla sınırlıdır ve bu sınırı uygulayan mekanizma HubOptions.MaximumReceiveMessageSize dir (varsayılan: 32 KB). JS.NET SignalR iletileri, MaximumReceiveMessageSize boyutundan daha büyükse hata verir. Çerçeve, hub'dan istemciye ileti SignalR boyutuna bir sınır getirmez. Boyut sınırı, hata iletileri ve ileti boyutu sınırlarıyla ilgili yönergeler hakkında daha fazla bilgi için bkz . ASP.NET Çekirdek BlazorSignalR kılavuzu.

Uygulamanın nerede çalıştığını belirleme

Uygulamanın birlikte çalışma çağrıları için kodun nerede çalıştığını bilmesi uygunsa, bileşenin WebAssembly'deki tarayıcı bağlamında yürütülüp yürütülmediğini belirlemek için JS kullanın OperatingSystem.IsBrowser .