Sdílet prostřednictvím


Interoperabilita JavaScriptu s ASP.NET Core Blazor (zprostředkovatel komunikace JS)

Poznámka:

Toto není nejnovější verze tohoto článku. Aktuální verzi najdete v tomto článku ve verzi .NET 9.

Upozorňující

Tato verze ASP.NET Core se už nepodporuje. Další informace najdete v zásadách podpory .NET a .NET Core. Aktuální verzi najdete v tomto článku ve verzi .NET 9.

Důležité

Tyto informace se týkají předběžného vydání produktu, který může být podstatně změněn před komerčním vydáním. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.

Aktuální verzi najdete v tomto článku ve verzi .NET 9.

Aplikace Blazor může volat funkce JavaScriptu (JS) z metod .NET a metody .NET z funkcí JS. Tyto scénáře se označují jako interoperabilita JavaScriptu (zprostředkovatel komunikace JS).

Další doprovodné materiály ke zprostředkovateli komunikace JS najdete v následujících článcích:

Poznámka:

Rozhraní API pro interoperabilitu JavaScriptu [JSImport]/[JSExport] je k dispozici pro komponenty na straně klienta v ASP.NET Core v .NET 7 nebo novějším.

Další informace naleznete v tématu JavaScript JSImport/JSExport interop s ASP.NET Core Blazor.

Komprese pro interaktivní součásti serveru s nedůvěryhodnými daty

Díky kompresi, která je ve výchozím nastavení povolená, se vyhněte vytváření zabezpečených (ověřených/autorizovaných) interaktivních komponent na straně serveru, které vykreslují data z nedůvěryhodných zdrojů. Mezi nedůvěryhodné zdroje patří parametry směrování, řetězce dotazů, data z JS interoperability a jakýkoli jiný zdroj dat, který může uživatel třetí strany řídit (databáze, externí služby). Další informace najdete v pokynech k ASP.NET CoreSignalR Blazora pokyny ke zmírnění hrozeb pro interaktivní vykreslování na straně serveru ASP.NET Core.Blazor

Balíček abstrakcí a funkcí v JavaScriptu

Balíček () (npmjs.comMicrosoft.JSInteropbalíček NuGet) poskytuje abstrakce a funkce pro interoperabilitu mezi kódem .NET a JavaScript (JS).@microsoft/dotnet-js-interop Referenční zdroj je k dispozici v dotnet/aspnetcore úložišti GitHub (/src/JSInterop složka). Další informace najdete v souboru úložiště README.md GitHub.

Poznámka:

Odkazy na dokumentaci k referenčnímu zdroji .NET obvykle načítají výchozí větev úložiště, která představuje aktuální vývoj pro příští verzi .NET. Pokud chcete vybrat značku pro konkrétní verzi, použijte rozevírací seznam pro přepnutí větví nebo značek. Další informace najdete v tématu Jak vybrat značku verze zdrojového kódu ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Další zdroje informací pro psaní JS skriptů zprostředkovatele komunikace v TypeScriptu:

Interakce s nástrojem DOM

Pouze ztlumení modelu DOM pomocí JavaScriptu (JS) v případech, kdy objekt nepracuje Blazor. Blazor udržuje reprezentaci modelu DOM a interaguje přímo s objekty DOM. Pokud se prvek vykreslený architekturou Blazor externě upraví přímo pomocí JS nebo prostřednictvím zprostředkovatele komunikace JS, nemusí se model DOM už shodovat s interní reprezentací v architektuře Blazor, což může vést k nedefinovanému chování. Nedefinované chování může narušovat prezentaci prvků nebo jejich funkcí, ale může také představovat bezpečnostní rizika pro aplikaci nebo server.

Tyto doprovodné materiály se vztahují nejen na váš vlastní kód zprostředkovatele komunikace JS, ale také na všechny knihovny JS, které aplikace používá, včetně čehokoli poskytovaného architekturou třetích stran, jako je například Bootstrap JS a jQuery.

V několika dokumentačních příkladech se zprostředkovatel komunikace JS používá k mutaci elementu výhradně pro demonstrační účely jako součást příkladu. V těchto případech se v textu zobrazí upozornění.

Další informace najdete v tématu Volání funkcí JavaScriptu z metod .NET v ASP.NET Core Blazor.

JavaScript – třída s polem funkce typu

Interoperabilita nepodporuje BlazorJS třídu JavaScriptu s polem funkce typu. Používejte javascriptové funkce ve třídách.

Nepodporováno: GreetingHelpers.sayHello V následující třídě jako pole funkce typu není zjištěno BlazorJS zprostředkovatele komunikace a nelze je spustit z kódu jazyka C#:

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

V následující třídě je podporována funkce:

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

Podporují se také funkce šipky:

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

Vyhněte se vložených obslužných rutin událostí

Funkci JavaScriptu lze vyvolat přímo z obslužné rutiny vložené události. V následujícím příkladu je javascriptová funkce volána při alertUser výběru tlačítka uživatelem:

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

Použití vložených obslužných rutin událostí je ale špatnou volbou návrhu pro volání funkcí JavaScriptu:

Doporučujeme vyhnout se vloženým obslužným rutinám událostí ve prospěch přístupů, které přiřazují obslužné rutiny v JavaScriptu, addEventListenerjak ukazuje následující příklad:

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)
            {
            }
        }
    }
}

V předchozím příkladu JSDisconnectedException je při vyřazení modulu zachycen v případě Blazorztráty okruhu SignalR . Pokud se předchozí kód použije v Blazor WebAssembly aplikaci, nedojde ke ztrátě připojeníSignalR, takže můžete odebrat blok a nechat řádek, který modul odstranícatch try-().await module.DisposeAsync(); Další informace najdete v tématu ASP.NET Interoperabilita Core Blazor JavaScriptu (JSinteroperabilita).

Další informace naleznete v následujících zdrojích:

Asynchronní volání JavaScriptu

JS interop volání jsou asynchronní, bez ohledu na to, zda je volaný kód synchronní nebo asynchronní. Volání jsou asynchronní, aby se zajistilo, že komponenty jsou kompatibilní napříč modely vykreslování na straně serveru a na straně klienta. Při přijímání vykreslování na straně serveru musí být volání zprostředkovatele komunikace asynchronní, JS protože se odesílají přes síťové připojení. U aplikací, které výhradně přijímají vykreslování na straně klienta, se podporují synchronní JS volání zprostředkovatele komunikace.

Serializace objektů

Blazor používá k serializaci System.Text.Json s následujícími požadavky a výchozím chováním:

  • Typy musí mít výchozí konstruktor, přístupové objekty get/set musí být veřejné a pole se nikdy serializují.
  • Globální výchozí serializaci nejde přizpůsobit, aby nedošlo k porušení stávajících knihoven komponent, dopadům na výkon a zabezpečení a snížení spolehlivosti.
  • Serializace názvů členů .NET vede k malým názvům klíčů JSON.
  • JSON je deserializován jako JsonElement instance jazyka C#, což umožňuje smíšené ukládání do velkého počtu instancí. Interní přetypování vlastností modelu jazyka C# funguje podle očekávání i přes všechny rozdíly mezi názvy klíčů JSON a názvy vlastností jazyka C#.
  • Komplexní typy rozhraní, jako KeyValuePairje například , mohou být oříznuty pomocí IL Trimmer při publikování a nejsou k dispozici pro JS interoperabilitu. Doporučujeme vytvořit vlastní typy pro typy, které oříznou il trimmer.
  • Blazorvždy spoléhá na reflexi serializace JSON, včetně při použití generování zdroje jazyka C#. Nastavení JsonSerializerIsReflectionEnabledByDefault v false souboru projektu aplikace způsobí chybu při pokusu o serializaci.

Rozhraní API JsonConverter je k dispozici pro vlastní serializaci. Vlastnosti mohou být označeny atributem [JsonConverter] pro přepsání výchozí serializace pro stávající datový typ.

Další informace najdete v následujících zdrojích informací v dokumentaci k .NET:

Blazor podporuje optimalizovaného zprostředkovatele komunikace JS pro bajtová pole, která zabraňuje kódování a dekódování bajtových polí do base64. Aplikace může použít vlastní serializaci a předat výsledné bajty. Další informace najdete v tématu Volání funkcí JavaScriptu z metod .NET v ASP.NET Core Blazor.

Blazor podporuje nezařazeného zprostředkovatele komunikace JS, pokud se rychle serializuje velký objem objektů .NET nebo pokud je potřeba serializovat velké objekty .NET nebo mnoho objektů .NET. Další informace najdete v tématu Volání funkcí JavaScriptu z metod .NET v ASP.NET Core Blazor.

Úlohy čištění DOM během odstraňování komponent

Neprovádějte JS kód zprostředkovatele komunikace pro úlohy čištění DOM během vyřazení komponent. Místo toho použijte MutationObserver vzor v JavaScriptu (JS) na klientovi z následujících důvodů:

  • Komponenta mohla být odebrána z MODELU DOM v době, kdy se kód čištění spustí v Dispose{Async}systému .
  • Během vykreslování Blazor na straně serveru může vykreslovací modul být uvolněn rozhraním v době, kdy se kód čištění spustí v Dispose{Async}.

Model MutationObserver umožňuje spustit funkci při odebrání elementu z modelu DOM.

V následujícím příkladu komponenta DOMCleanup :

  • Obsahuje s příponou <div> id cleanupDiv. Prvek <div> je odebrán z MODELU DOM spolu s rest kódem MODELU DOM komponenty, když je komponenta odebrána z modelu DOM.
  • DOMCleanupJS Načte třídu ze DOMCleanup.razor.js souboru a zavolá její createObserver funkci pro nastavení zpětného MutationObserver volání. Tyto úlohy se provádějí v OnAfterRenderAsync metodě životního cyklu.

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)
            {
            }
        }
    }
}

V předchozím příkladu JSDisconnectedException je při vyřazení modulu zachycen v případě Blazorztráty okruhu SignalR . Pokud se předchozí kód použije v Blazor WebAssembly aplikaci, nedojde ke ztrátě připojeníSignalR, takže můžete odebrat blok a nechat řádek, který modul odstranícatch try-().await module.DisposeAsync(); Další informace najdete v tématu ASP.NET Interoperabilita Core Blazor JavaScriptu (JSinteroperabilita).

V následujícím příkladu MutationObserver se zpětné volání provede pokaždé, když dojde ke změně DOM. Spusťte kód čištění, když příkaz if potvrdí, že cílový element (cleanupDiv) byl odebrán (if (targetRemoved) { ... }). Je důležité odpojit a odstranit MutationObserver , aby nedošlo k nevrácení paměti po spuštění kódu čištění.

DOMCleanup.razor.js umístěné vedle předchozí DOMCleanup součásti:

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;

Volání zprostředkovatele komunikace JavaScriptu bez okruhu

Tato část se týká jenom aplikací na straně serveru.

Volání zprostředkovatele komunikace JavaScriptu (JS) nelze vydat po Blazorodpojení okruhu SignalR . Bez okruhu během odstraňování součástí nebo v jakémkoli jiném okamžiku, kdy okruh neexistuje, následující volání metody selžou a zapíše zprávu, že okruh je odpojen jako JSDisconnectedException:

Abyste se vyhnuli protokolování JSDisconnectedException nebo protokolování vlastních informací, zachyťte výjimku v try-catch příkazu.

Příklad vyřazení z následujících součástí:

  • Komponenta na straně serveru implementuje IAsyncDisposable.
  • module je pro IJSObjectReference JS modul.
  • JSDisconnectedException je zachycen a nezaprotokolován.
  • Volitelně můžete vlastní informace v catch příkazu protokolovat na libovolné úrovni protokolu, kterou dáváte přednost. Následující příklad nezapíše vlastní informace, protože předpokládá, že vývojář nezajímá, kdy nebo kde jsou okruhy odpojeny během vyřazení komponent.
async ValueTask IAsyncDisposable.DisposeAsync()
{
    try
    {
        if (module is not null)
        {
            await module.DisposeAsync();
        }
    }
    catch (JSDisconnectedException)
    {
    }
}

Pokud po ztrátě okruhu v aplikaci na straně Blazor serveru musíte vyčistit vlastní JS objekty nebo na klientovi spustit jiný JS kód, použijte MutationObserver v klientovi vzorJS. Model MutationObserver umožňuje spustit funkci při odebrání elementu z modelu DOM.

Další informace najdete v následujících článcích:

Soubory JavaScriptu uložené v mezipaměti

Soubory JavaScriptu (JS) a další statické prostředky nejsou během vývoje v prostředí Development obecně uložené v mezipaměti na klientech. Požadavky na statické prostředky během vývoje zahrnují hlavičku Cache-Control header s hodnotou no-cache nebo max-age s hodnotou nula (0).

V produkční fázi jsou v prostředí Production soubory JS obvykle klienty ukládány do mezipaměti.

Pokud vývojáři chtějí v prohlížečích zakázat ukládání do mezipaměti na straně klienta, obvykle využívají jeden z následujících přístupů:

  • Zákaz ukládání do mezipaměti, když je otevřená konzola vývojářských nástrojů prohlížeče. Pokyny najdete v dokumentaci k vývojářským nástrojům každého správce prohlížeče:
  • Ruční aktualizace prohlížeče pro všechny webové stránky aplikace Blazor, aby se znovu načetly soubory JS ze serveru. Middleware HTTP Caching pro ASP.NET Core vždy podporuje platnou hlavičku Cache-Control odeslanou klientem.

Další informace naleznete v tématu:

Omezení velikosti pro volání zprostředkovatele komunikace JavaScriptu

Tato část se týká jenom interaktivních komponent v aplikacích na straně serveru. U komponent na straně klienta architektura neomezuje velikost vstupů a výstupů z interoperability JavaScriptuJS.

U interaktivních komponent v aplikacích JS na straně serveru jsou volání zprostředkovatele komunikace předávající data ze serveru omezena maximální velikostí příchozích SignalR zpráv povolených pro metody centra, která se vynucuje HubOptions.MaximumReceiveMessageSize (ve výchozím nastavení: 32 kB). JS zprávy .NET SignalR větší než MaximumReceiveMessageSize vyvolá chybu. Architektura neukládá omezení velikosti SignalR zprávy z centra na klienta. Další informace o limitu velikosti, chybových zprávách a doprovodných materiálech k řešení limitů velikosti zpráv najdete v ASP.NET BlazorSignalR základních doprovodných materiálech.

Určení, kde je aplikace spuštěná

Pokud je relevantní, aby aplikace věděla, kde je kód spuštěný pro JS volání zprostředkovatele komunikace, použijte OperatingSystem.IsBrowser k určení, jestli se komponenta spouští v kontextu prohlížeče ve službě WebAssembly.