Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Observação
Esta não é a versão mais recente deste artigo. Para a versão atual, consulte a versão .NET 10 deste artigo.
Advertência
Esta versão do ASP.NET Core não é mais suportada. Para obter mais informações, consulte a Política de suporte do .NET e .NET Core. Para a versão atual, consulte a versão .NET 9 deste artigo.
Um aplicativo Blazor pode invocar funções JavaScript (JS) de métodos .NET e métodos .NET de funções JS. Esses cenários são chamados de interoperabilidade JavaScript (JS interop).
Outras orientações de JS interoperabilidade são fornecidas nos seguintes artigos:
- Chamar funções JavaScript a partir de métodos .NET no ASP.NET Core Blazor
- Chamar métodos .NET a partir de funções JavaScript no ASP.NET Core Blazor
- Práticas recomendadas de desempenho de interoperabilidade de JavaScript (Blazor iteroperabilidade) no ASP.NET Core JS
Observação
API de interoperabilidade JavaScript [JSImport]/[JSExport] está disponível para componentes do lado do cliente no ASP.NET Core em .NET 7 ou posterior.
Para obter mais informações, consulte Interoperabilidade JSImport/JSExport JavaScript com ASP.NET Core Blazor.
Compactação para componentes de servidor interativos com dados não confiáveis
Com a compactação, que é habilitada por padrão, evite criar componentes interativos seguros (autenticados/autorizados) do lado do servidor que renderizam dados de fontes não confiáveis. As fontes não confiáveis incluem parâmetros de rota, cadeias de caracteres de consulta, dados de interoperabilidade JS e qualquer outra fonte de dados que um usuário de terceiros possa controlar (bancos de dados, serviços externos). Para obter mais informações, consulte orientação do ASP.NET Core BlazorSignalR e Orientação de mitigação de ameaças para ASP.NET Core Blazor renderização interativa do lado do servidor.
Pacote de abstrações e recursos de interoperabilidade do JavaScript
O pacote @microsoft/dotnet-js-interop (npmjs.com) (Microsoft.JSInterop pacote NuGet) fornece abstrações e recursos para interoperabilidade entre o código .NET e JavaScript (JS). A fonte de referência está disponível no repositório dotnet/aspnetcore GitHub (pasta/src/JSInterop). Para obter mais informações, consulte o arquivo README.md do repositório GitHub.
Observação
Os links de documentação para a fonte de referência do .NET geralmente carregam a ramificação padrão do repositório, que representa o desenvolvimento atual para a próxima versão do .NET. Para selecionar uma tag para uma versão específica, use a lista suspensa de ramificações ou tags . Para obter mais informações, consulte Como selecionar uma marca de versão do código-fonte do ASP.NET Core (dotnet/AspNetCore.Docs #26205).
Recursos adicionais para escrever scripts de interoperabilidade JS no TypeScript:
- TypeScript
- Tutorial: Criar um aplicativo ASP.NET Core com TypeScript no Visual Studio
- Gerenciar pacotes npm no Visual Studio
Interação com o DOM
Apenas altere o DOM com JavaScript (JS) quando o objeto não interagir com Blazor. Blazor mantém representações do DOM e interage diretamente com objetos DOM. Se um elemento renderizado por Blazor for modificado externamente usando JS diretamente ou por meio de JS Interoperabilidade, o DOM pode não corresponder mais à representação interna do Blazor, o que pode resultar em comportamento indefinido. O comportamento indefinido pode apenas interferir com a apresentação de elementos ou suas funções, mas também pode introduzir riscos de segurança para o aplicativo ou servidor.
Esta orientação não se aplica apenas ao seu próprio código de interoperabilidade JS, mas também a quaisquer bibliotecas JS que o aplicativo usa, incluindo qualquer coisa fornecida por uma estrutura de terceiros, como Bootstrap JS e jQuery.
Em alguns exemplos de documentação, utiliza-se JS interop para alterar um elemento puramente para fins de demonstração. Nesses casos, aparece um aviso no texto.
Para obter mais informações, veja Executar funções JavaScript a partir de métodos .NET no ASP.NET Core Blazor.
Classe JavaScript com uma função de campo de tipo
Uma classe JavaScript com um campo do tipo função não é suportada pela interoperabilidade BlazorJS. Use funções Javascript em classes.
Sem suporte:GreetingHelpers.sayHello na seguinte classe, um campo do tipo função não é identificado pela interoperabilidade de Blazor com o JS e não pode ser executado a partir do código C#:
export class GreetingHelpers {
sayHello = function() {
...
}
}
suportados:GreetingHelpers.sayHello é suportada como uma função na seguinte classe:
export class GreetingHelpers {
sayHello() {
...
}
}
As funções de seta também são suportadas:
export class GreetingHelpers {
sayHello = () => {
...
}
}
Evite manipuladores de eventos embutidos
Uma função JavaScript pode ser invocada diretamente de um manipulador de eventos embutido. No exemplo a seguir, alertUser é uma função JavaScript chamada quando o botão é selecionado pelo usuário:
<button onclick="alertUser">Click Me!</button>
No entanto, o uso de manipuladores de eventos embutidos é uma má escolha de design para a chamada de funções JavaScript:
- Misturar marcação HTML e código JavaScript muitas vezes leva a um código insustentável.
- A execução do manipulador de eventos em linha pode ser bloqueada por um Content Security Policy (CSP) (documentação MDN).
Recomendamos evitar manipuladores de eventos embutidos em favor de abordagens que atribuem manipuladores em JavaScript com addEventListener, como demonstra o exemplo a seguir:
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)
{
}
}
}
}
No exemplo anterior, JSDisconnectedException fica preso durante a desativação do módulo, caso o circuito Blazor de SignalRseja perdido. Se o código anterior for usado numa aplicação Blazor WebAssembly, não há conexão SignalR a perder, por isso pode-se remover o bloco de try-catch e deixar a linha que descarta o módulo (await module.DisposeAsync();). Para obter mais informações, consulte ASP.NET Core Blazor interoperabilidade do JavaScript (JS interop).
Para obter mais informações, consulte os seguintes recursos:
- Localização do JavaScript nas aplicações ASP.NET Core Blazor
- Introdução aos eventos (documentação MDN)
Chamadas JavaScript assíncronas
JS As chamadas de interoperabilidade são assíncronas, independentemente de o código chamado ser assíncrono ou síncrono. As chamadas são assíncronas para garantir que os componentes sejam compatíveis entre modelos de renderização do lado do servidor e do lado do cliente. Ao adotar a renderização do lado do servidor, as chamadas de interop JS devem ser assíncronas porque são enviadas por uma conexão de rede. Para aplicações que adotam exclusivamente a renderização do lado do cliente, são suportadas chamadas de interoperabilidade síncronas JS.
Para obter mais informações, consulte os seguintes artigos:
Para obter mais informações, veja Executar funções JavaScript a partir de métodos .NET no ASP.NET Core Blazor.
Serialização de objetos
Blazor usa System.Text.Json para serialização com os seguintes requisitos e comportamentos padrão:
- Os tipos devem ter um construtor padrão,
get/setacessadores devem ser públicos e os campos nunca são serializados. - A serialização padrão global não é personalizável para evitar a quebra de bibliotecas de componentes existentes, impactos no desempenho e na segurança e reduções na confiabilidade.
- A serialização de nomes de membros do .NET resulta em nomes de chave JSON minúsculos.
- JSON é desserializado como JsonElement instâncias C#, que permitem caixa mista. A conversão interna para atribuição a propriedades de modelo C# funciona conforme o esperado, apesar de quaisquer diferenças de caso entre nomes de chave JSON e nomes de propriedade C#.
- Tipos de estrutura complexos podem ser cortados pelo IL Trimmer na publicação e não estão presentes para JS interoperabilidade ou serialização/desserialização JSON. Recomendamos a criação de tipos personalizados para tipos que a ferramenta IL Trimmer remove.
-
Blazor sempre depende de reflexão para a serialização em JSON, incluindo quando se usa a geração de código-fonte em C# . Definir
JsonSerializerIsReflectionEnabledByDefaultparafalseno arquivo de projeto do aplicativo resulta em um erro quando a serialização é tentada.
JsonConverter API está disponível para serialização personalizada. As propriedades podem ser anotadas com um atributo [JsonConverter] para substituir a serialização padrão de um tipo de dados existente.
Para obter mais informações, consulte os seguintes recursos na documentação do .NET:
- serialização e desserialização JSON (empacotamento e desempacotamento) no .NET
-
Como personalizar nomes e valores de propriedade com
System.Text.Json - Como escrever conversores personalizados para serialização JSON (marshalling) no .NET
Blazor suporta interoperabilidade de matriz de bytes otimizada que evita a codificação/decodificação de matrizes de bytes em Base64. O aplicativo pode aplicar serialização personalizada e passar os bytes resultantes. Para obter mais informações, veja Executar funções JavaScript a partir de métodos .NET no ASP.NET Core Blazor.
Blazor oferece suporte a interoperabilidade JS sem empacotamento quando um grande volume de objetos .NET é rapidamente serializado ou quando grandes ou muitos objetos .NET devem ser serializados. Para obter mais informações, veja Executar funções JavaScript a partir de métodos .NET no ASP.NET Core Blazor.
Tarefas de limpeza do DOM durante o descarte de componentes
Não execute o código de interoperabilidade JS para tarefas de limpeza de DOM durante a eliminação de componentes. Em vez disso, use o padrão MutationObserver em JavaScript (JS) no cliente pelos seguintes motivos:
- O componente pode ter sido removido do DOM no momento em que o código de limpeza é executado no
Dispose{Async}. - Durante a renderização do lado do servidor, o renderizador de Blazor pode ter sido descartado pelo framework no momento em que o código de finalização é executado no
Dispose{Async}.
O padrão MutationObserver permite executar uma função quando um elemento é removido do DOM.
No exemplo a seguir, o componente DOMCleanup:
- Contém um
<div>com umiddecleanupDiv. O elemento<div>é removido do DOM junto com o restante da marcação DOM do componente quando o componente é removido do DOM. - Carrega a classe
DOMCleanupJS do ficheiroDOMCleanup.razor.jse chama a sua funçãocreateObserverpara configurar a chamada de retornoMutationObserver. Essas tarefas são realizadas no método de ciclo de vidaOnAfterRenderAsync.
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)
{
}
}
}
}
No exemplo anterior, JSDisconnectedException fica preso durante a desativação do módulo, caso o circuito Blazor de SignalRseja perdido. Se o código anterior for usado numa aplicação Blazor WebAssembly, não há conexão SignalR a perder, por isso pode-se remover o bloco de try-catch e deixar a linha que descarta o módulo (await module.DisposeAsync();). Para obter mais informações, consulte ASP.NET Core Blazor interoperabilidade do JavaScript (JS interop).
No exemplo a seguir, o retorno de chamada MutationObserver é executado sempre que ocorre uma alteração no DOM. Execute o seu código de limpeza quando a instrução if confirmar que o elemento alvo (cleanupDiv) foi removido (if (targetRemoved) { ... }). É importante desconectar e excluir o MutationObserver para evitar um vazamento de memória após a execução do código de limpeza.
DOMCleanup.razor.js colocado lado a lado com o componente precedente DOMCleanup:
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;
As abordagens anteriores anexam o MutationObserver ao target.parentNode, que funciona até que parentNode em si seja removido do DOM. Esse é um cenário comum, por exemplo, ao navegar para uma nova página, o que faz com que todo o componente da página seja removido do DOM. Nesses casos, os componentes filhos que observam alterações na página não são limpos corretamente.
Não assuma que observar document.body, em vez de target.parentNode, é um alvo melhor. Observar document.body tem implicações de desempenho porque a lógica de retorno de chamada é executada para todas as atualizações DOM, independentemente de terem ou não algo a ver com seu elemento. Use uma das seguintes abordagens:
- Nos casos em que você pode identificar um nó ancestral adequado para observar, use
MutationObservercom ele. Idealmente, esse ancestral tem como escopo as mudanças que você deseja observar, em vez dedocument.body. - Em vez de usar
MutationObserver, considere usar um elemento personalizado edisconnectedCallback. O evento é sempre acionado quando o seu elemento personalizado é desconectado, independentemente de onde esteja localizado no DOM em relação às alterações no DOM.
Chamadas de interoperabilidade JavaScript sem circuito
Esta secção aplica-se apenas a aplicações do lado do servidor.
As chamadas de interoperabilidade JavaScript (JS) não podem ser emitidas depois de o circuito de Blazor do SignalRser desconectado. Na ausência de um circuito durante a eliminação do componente ou em qualquer outro momento em que um circuito não exista, as seguintes chamadas de método falham e registam uma mensagem indicando que o circuito está desconectado como um JSDisconnectedException:
- JS chamadas de método de interoperabilidade
-
Dispose/DisposeAsyncapela a qualquer IJSObjectReference.
- JS chamadas de método de interoperabilidade
-
Dispose/DisposeAsyncapela a qualquer IJSObjectReference.
Para evitar registar JSDisconnectedException ou registar informações personalizadas, capture a exceção numa instrução try-catch.
Para o seguinte exemplo de eliminação de componentes:
- O componente do lado do servidor implementa IAsyncDisposable.
-
moduleé um IJSObjectReference para um módulo JS. - JSDisconnectedException é capturado e não registado.
- Opcionalmente, você pode registrar informações personalizadas na instrução
catchem qualquer nível de log que preferir. O exemplo a seguir não registra informações personalizadas porque pressupõe que o desenvolvedor não se importa com quando ou onde os circuitos são desconectados durante a eliminação de componentes.
async ValueTask IAsyncDisposable.DisposeAsync()
{
try
{
if (module is not null)
{
await module.DisposeAsync();
}
}
catch (JSDisconnectedException)
{
}
}
Se você precisar limpar seus próprios objetos JS ou executar outro código JS no cliente depois que um circuito for perdido em um aplicativo de Blazor do lado do servidor, use o padrão MutationObserver em JS no cliente. O padrão MutationObserver permite executar uma função quando um elemento é removido do DOM.
Para obter mais informações, consulte os seguintes artigos:
- Manipular erros em aplicações ASP.NET Core Blazor: A seção de interoperação JavaScript discute o tratamento de erros em cenários de interoperação JS.
Eliminação de componentes do ASP.NET Core : O artigo descreve como implementar padrões de eliminação em componentes .
Arquivos JavaScript armazenados em cache
Arquivos JavaScript (JS) e outros ativos estáticos geralmente não são armazenados em cache nos clientes durante o desenvolvimento no ambiente Development. Durante o desenvolvimento, as solicitações de ativos estáticos incluem o cabeçalho Cache-Control com um valor de no-cache ou max-age com um valor de zero (0).
Durante a produção no ambiente Production, os arquivos JS geralmente são armazenados em cache pelos clientes.
Para desativar o cache do lado do cliente nos navegadores, os desenvolvedores geralmente adotam uma das seguintes abordagens:
- Desative o cache quando o console de ferramentas de desenvolvedor do navegador estiver aberto. A orientação pode ser encontrada na documentação das ferramentas de desenvolvedor de cada mantenedor do navegador:
- Execute uma atualização manual do navegador de qualquer página da Web do aplicativo Blazor para recarregar os arquivos JS do servidor. O Middleware de Cache de HTTP do ASP.NET Core sempre respeita um cabeçalho
Cache-Controlno-cache válido enviado por um cliente.
Para mais informações, consulte:
Limites de tamanho em chamadas de interoperabilidade JavaScript
Esta seção só se aplica a componentes interativos em aplicativos do lado do servidor. Para componentes do lado do cliente, o framework não impõe um limite ao tamanho das entradas e saídas de interoperabilidade JavaScript (JS).
Para componentes interativos em aplicativos no lado do servidor, as chamadas JS de interoperabilidade que passam dados do cliente para o servidor são limitadas em tamanho pelo tamanho máximo da mensagem de entrada SignalR permitido para os métodos do hub, controlado por HubOptions.MaximumReceiveMessageSize (padrão: 32 KB). JS para .NET SignalR mensagens maiores que MaximumReceiveMessageSize geram um erro. A estrutura não impõe um limite ao tamanho de uma mensagem SignalR do hub para um cliente. Para obter mais informações sobre o limite de tamanho, mensagens de erro e orientações sobre como lidar com limites de tamanho de mensagem, consulte ASP.NET Core BlazorSignalR guidance.
Determinar onde o aplicativo está sendo executado
Se for relevante para o aplicativo saber onde o código para as chamadas de interoperabilidade JS está a ser executado, use OperatingSystem.IsBrowser para determinar se o componente está a ser executado no contexto do navegador em WebAssembly.