Ler em inglês

Partilhar via


Modos de renderização do ASP.NET Core Blazor

Nota

Esta não é a versão mais recente deste artigo. Para a versão atual, consulte a versão .NET 9 deste artigo.

Importante

Estas informações referem-se a um produto de pré-lançamento que pode ser substancialmente modificado antes de ser lançado comercialmente. A Microsoft não oferece garantias, expressas ou implícitas, em relação às informações fornecidas aqui.

Para a versão atual, consulte a versão .NET 9 deste artigo.

Este artigo explica o controle da renderização de componentes Razor em Blazor Web Apps, em tempo de compilação ou tempo de execução.

Estas orientações não se aplicam a aplicações Blazor WebAssembly autónomas. Blazor WebAssembly aplicações são renderizadas apenas no lado do cliente por meio de um tempo de execução no lado do cliente baseado em WebAssembly e não possuem qualquer conceito de modo de renderização . Se um modo de renderização for aplicado a um componente em um aplicativo Blazor WebAssembly, a designação do modo de renderização não terá influência na renderização do componente.

Modos de renderização

Cada componente em um Blazor Web App adota um modo de renderização para determinar o modelo de hospedagem que ele usa, onde é renderizado e se é interativo ou não.

A tabela a seguir mostra os modos de renderização disponíveis para renderizar componentes Razor num Blazor Web App. Para aplicar um modo de renderização a um componente, use a diretiva @rendermode na instância do componente ou na definição do componente. Mais adiante neste artigo, exemplos são mostrados para cada cenário de modo de renderização.

Nome Descrição Local de renderização Interativo
Servidor estático Renderização estática do lado servidor (SSR estático) Servidor Não
Servidor Interativo Renderização interativa do lado do servidor (SSR interativo) usando Blazor Server. Servidor ✔️ Sim
WebAssembly Interativa Renderização do lado do cliente (CSR) usando Blazor WebAssembly†. Cliente ✔️ Sim
Auto interativo SSR interativo usando Blazor Server inicialmente e, em seguida, CSR em visitas subsequentes após o download do pacote Blazor. Servidor e, em seguida, cliente ✔️ Sim

†A renderização do lado do cliente (CSR) é assumida como interativa. "Interactive client-side rendering" e "interactive CSR" não são usados pela indústria nem na documentação Blazor.

A pré-renderização é habilitada por padrão para componentes interativos. Orientações sobre como controlar a pré-renderização são fornecidas mais adiante neste artigo. Para obter a terminologia geral do setor sobre conceitos de renderização de cliente e servidor, consulte ASP.NET Core Blazor Fundamentos.

Os exemplos a seguir demonstram a configuração do modo de renderização do componente com alguns recursos básicos do componente Razor.

Para testar os comportamentos do modo de renderização localmente, você pode colocar os seguintes componentes em um aplicativo criado a partir do modelo de projeto Blazor Web App. Ao criar o aplicativo, selecione opções nos menus suspensos (Visual Studio) ou aplique as opções da CLI (CLI .NET) para habilitar a interatividade do lado do servidor e do lado do cliente. Para obter orientação sobre como criar um Blazor Web App, consulte Tooling for ASP.NET Core Blazor.

Habilite o suporte para modos de renderização interativos

Um Blazor Web App deve ser configurado para suportar modos de renderização interativos. As extensões a seguir são aplicadas automaticamente a aplicativos criados a partir do modelo de projeto Blazor Web App durante a criação do aplicativo. Os componentes individuais ainda são obrigados a declarar o seu modo de renderização de acordo com a secção Modos de renderização depois de os serviços de componentes e os pontos de extremidade serem configurados no ficheiro Program da aplicação.

Os serviços de componentes Razor são adicionados ao chamar AddRazorComponents.

Extensões do construtor de componentes:

MapRazorComponents descobre os componentes disponíveis e especifica o componente raiz do aplicativo (o primeiro componente carregado), que por padrão é o componente App (App.razor).

Extensões do construtor de convenções de pontos finais:

Nota

Para obter orientação sobre o posicionamento da API nos exemplos a seguir, inspecione o arquivo de Program de um aplicativo gerado a partir do modelo de projeto Blazor Web App. Para obter orientação sobre como criar um Blazor Web App, consulte Tooling for ASP.NET Core Blazor.

Exemplo 1: A seguinte API de arquivo Program adiciona serviços e configuração para habilitar o SSR interativo:

C#
builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents();
C#
app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode();

Exemplo 2: A API de arquivo Program a seguir adiciona serviços e configuração para habilitar o modo de renderização do Interactive WebAssembly:

C#
builder.Services.AddRazorComponents()
    .AddInteractiveWebAssemblyComponents();
C#
app.MapRazorComponents<App>()
    .AddInteractiveWebAssemblyRenderMode();

Exemplo 3: A API de arquivo Program a seguir adiciona serviços e configuração para habilitar os modos Servidor Interativo, WebAssembly Interativo e Renderização Automática Interativa:

C#
builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents()
    .AddInteractiveWebAssemblyComponents();
C#
app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode()
    .AddInteractiveWebAssemblyRenderMode();

Blazor usa o modelo de hospedagem Blazor WebAssembly para baixar e executar componentes que usam o modo de renderização Interactive WebAssembly. Um projeto de cliente separado é necessário para configurar Blazor WebAssembly hospedagem para esses componentes. O projeto cliente contém o código de inicialização para o host Blazor WebAssembly e configura o tempo de execução do .NET para execução em um navegador. O modelo Blazor Web App adiciona esse projeto de cliente para você quando você seleciona a opção para habilitar a interatividade WebAssembly. Todos os componentes que usam o modo de renderização Interactive WebAssembly devem ser criados a partir do projeto cliente, para que sejam incluídos no pacote de aplicativos baixados.

Aplicar um modo de renderização a uma instância de componente

Para aplicar um modo de renderização a uma instância de componente, use o atributo de diretiva @rendermodeRazor onde o componente é usado.

No exemplo a seguir, a renderização interativa do lado do servidor (SSR interativo) é aplicada à instância do componente Dialog:

razor
<Dialog @rendermode="InteractiveServer" />

Nota

Blazor modelos incluem uma diretiva using estática para RenderMode no arquivo de _Imports do aplicativo (Components/_Imports.razor) para sintaxe @rendermode mais curta:

razor
@using static Microsoft.AspNetCore.Components.Web.RenderMode

Sem a diretiva anterior, os componentes devem especificar a classe estática RenderMode na sintaxe @rendermode.

razor
<Dialog @rendermode="RenderMode.InteractiveServer" />

Você também pode fazer referência a instâncias de modo de renderização personalizadas instanciadas diretamente com a configuração personalizada. Para obter mais informações, consulte a seção Modos de renderização abreviados personalizados mais adiante neste artigo.

Aplicar um modo de renderização a uma definição de componente

Para especificar o modo de renderização para um componente como parte de sua definição, use a diretiva @rendermodeRazor e o atributo de modo de renderização correspondente.

razor
@page "..."
@rendermode InteractiveServer

A aplicação de um modo de renderização a uma definição de componente é comumente usada ao aplicar um modo de renderização a uma página específica. As páginas roteáveis usam o mesmo modo de renderização que o componente Router que renderizou a página.

Tecnicamente, @rendermode é simultaneamente uma diretiva Razor e uma diretiva Razoratributo. A semântica é semelhante, mas há diferenças. A diretiva @rendermode está na definição do componente, portanto, a instância do modo de renderização referenciada deve ser estática. O atributo de diretiva @rendermode pode usar qualquer instância de modo de renderização.

Nota

Os autores de componentes devem evitar acoplar a implementação de um componente a um modo de renderização específico. Em vez disso, os autores de componentes normalmente devem projetar componentes para suportar qualquer modo de renderização ou modelo de hospedagem. A implementação de um componente deve evitar suposições sobre onde está sendo executado (servidor ou cliente) e deve degradar graciosamente quando renderizado de forma estática. Especificar o modo de renderização na definição do componente pode ser necessário se o componente não for instanciado diretamente (como com um componente de página roteável) ou para especificar um modo de renderização para todas as instâncias do componente.

Aplicar um modo de renderização a todo o aplicativo

Para definir o modo de renderização para todo o aplicativo, indique o modo de renderização no componente interativo de nível mais alto na hierarquia de componentes do aplicativo que não seja um componente raiz.

Nota

Não há suporte para tornar um componente raiz interativo, como o componente App. Portanto, o modo de renderização para todo o aplicativo não pode ser definido diretamente pelo componente App.

Para aplicativos baseados no modelo de projeto Blazor Web App, um modo de renderização atribuído ao aplicativo inteiro normalmente é especificado onde o componente Routes é usado no componente App (Components/App.razor):

razor
<Routes @rendermode="InteractiveServer" />

O componente Router propaga seu modo de renderização para as páginas que rota.

Normalmente, você também deve definir o mesmo modo de renderização interativo no componente HeadOutlet, que também é encontrado no componente App de um Blazor Web App gerado a partir do modelo de projeto:

<HeadOutlet @rendermode="InteractiveServer" />

Para aplicativos que adotam um modo de renderização interativo do lado do cliente (WebAssembly ou Auto) e habilitam o modo de renderização para todo o aplicativo por meio do componente Routes:

  • Coloque ou mova os arquivos de layout e navegação da pasta Components/Layout do aplicativo de servidor para a pasta .Client do projeto Layout. Crie uma pasta Layout no projeto .Client se ela não existir.
  • Coloque ou mova os componentes da pasta Components/Pages do aplicativo de servidor para a pasta .Client do projeto Pages. Crie uma pasta Pages no projeto .Client se ela não existir.
  • Coloque ou mova o componente Routes da pasta Components do aplicativo de servidor para a pasta raiz do projeto .Client.

Para permitir a interatividade global ao criar um Blazor Web App:

  • Visual Studio: defina o local de Interatividade lista suspensa como Global.
  • CLI do .NET: Use a opção -ai|--all-interactive.

Para obter mais informações, consulte Tooling for ASP.NET Core Blazor.

Aplicar um modo de renderização programaticamente

Propriedades e campos podem atribuir um modo de renderização.

A segunda abordagem descrita nesta seção, definindo o modo de renderização por instância de componente, é especialmente útil quando a especificação do aplicativo exige que um ou mais componentes adotem SSR estático em um aplicativo interativo. Esse cenário é abordado na seção SSR estático em um aplicativo interativo mais adiante neste artigo.

Definir o modo de renderização por definição de componente

Uma definição de componente pode definir um modo de renderização através de um campo privado:

razor
@rendermode pageRenderMode

...

@code {
    private static IComponentRenderMode pageRenderMode = InteractiveServer;
}

Definir o modo de renderização por instância do componente

O exemplo a seguir aplica a renderização interativa do lado do servidor (SSR interativo) a qualquer solicitação.

razor
<Routes @rendermode="PageRenderMode" />

...

@code {
    private IComponentRenderMode? PageRenderMode => InteractiveServer;
}

Informações adicionais sobre a propagação do modo de renderização são fornecidas na seção Propagação do modo de renderização mais adiante neste artigo. As páginas SSR estáticas na seção de um aplicativo interativo mostram como usar a abordagem anterior para adotar SSR estático em um aplicativo interativo.

Detetar o local de renderização, a interatividade e o modo de renderização atribuído em tempo de execução

As propriedades ComponentBase.RendererInfo e ComponentBase.AssignedRenderMode permitem que o aplicativo detete detalhes sobre o local, a interatividade e o modo de renderização atribuído de um componente:

  • RendererInfo.Name retorna o local onde o componente está sendo executado:
    • Static: No servidor (SSR) e incapaz de interatividade.
    • Server: No servidor (SSR) e capaz de ser interativo após a prerenderização.
    • WebAssembly: No cliente (CSR) e com capacidade de interatividade após a pré-renderização.
    • WebView: No dispositivo nativo e capaz de interatividade após a pré-renderização.
  • RendererInfo.IsInteractive indica se o componente suporta interatividade no momento da renderização. O valor é true ao renderizar interativamente ou false ao pré-renderizar ou para SSR estático (RendererInfo.Name de Static).
  • AssignedRenderMode expõe o modo de renderização atribuído ao componente:
    • InteractiveServerRenderMode para o Servidor Interativo.
    • InteractiveAutoRenderMode para Interactive Auto.
    • InteractiveWebAssemblyRenderMode para WebAssembly interativo.
    • null se um modo de renderização não estiver atribuído.

Os componentes usam essas propriedades para renderizar conteúdo dependendo de seu local ou status de interatividade. Os exemplos a seguir demonstram casos de uso típicos.

Exibir conteúdo até que um componente seja interativo:

razor
@if (!RendererInfo.IsInteractive)
{
    <p>Connecting to the assistant...</p>
}
else
{
    ...
}

Desative um botão até que um componente seja interativo:

razor
<button @onclick="Send" disabled="@(!RendererInfo.IsInteractive)">
    Send
</button>

Desabilite um formulário durante a pré-renderização e habilite o formulário quando o componente for interativo:

razor
<EditForm Model="Movie" ...>
    <fieldset disabled="@disabled">

        ...

        <button type="submit" >Save</button>
    </fieldset>
</EditForm>

@code {
    private bool disabled = true;

    [SupplyParameterFromForm]
    private Movie? Movie { get; set; }

    protected override async Task OnInitializedAsync()
    {
        Movie ??= await ...;

        if (RendererInfo.IsInteractive)
        {
            disabled = false;
        }
    }
}

Renderize a marcação para dar suporte à execução de uma ação HTML regular se o componente for renderizado estaticamente:

razor
@if (AssignedRenderMode is null)
{
    // The render mode is Static Server
    <form action="/movies">
        <input type="text" name="titleFilter" />
        <input type="submit" value="Search" />
    </form>
}
else
{
    // The render mode is Interactive Server, WebAssembly, or Auto
    <input @bind="titleFilter" />
    <button @onclick="FilterMovies">Search</button>
}

No exemplo anterior:

  • Quando o valor de AssignedRenderMode é null, o componente adota SSR estático. Blazor manipulação de eventos não é funcional em um navegador com SSR estático, portanto, o componente envia um formulário (solicitação GET) com uma cadeia de caracteres de consulta titleFilter definida para o valor <input> do usuário. O componente Movie (/movie) pode ler a cadeia de caracteres de consulta e processar o valor de titleFilter para renderizar o componente com os resultados filtrados.
  • Caso contrário, o modo de renderização é qualquer um dos InteractiveServer, InteractiveWebAssemblyou InteractiveAuto. O componente é capaz de usar um delegado do manipulador de eventos (FilterMovies) e o valor vinculado ao elemento <input> (titleFilter) para filtrar filmes interativamente através da conexão em segundo plano SignalR.

Blazor exemplos de documentação para Blazor Web Apps

Ao usar um Blazor Web App, a maioria dos componentes de exemplo de documentação Blazorexigem interatividade para funcionar e demonstrar os conceitos cobertos pelos artigos. Ao testar um componente de exemplo fornecido por um artigo, verifique se o aplicativo adota interatividade global ou se o componente adota um modo de renderização interativo.

Pré-renderização

Pré-renderização é o processo de renderizar inicialmente o conteúdo da página no servidor sem ativar manipuladores de eventos para os controlos renderizados. O servidor emite a interface HTML da página o mais rápido possível em resposta à solicitação inicial, o que proporciona uma experiência mais responsiva aos utilizadores. A pré-renderização também pode melhorar a otimização de motores de busca (SEO), renderizando conteúdo para a resposta HTTP inicial que os motores de pesquisa usam para calcular o ranking da página.

A pré-renderização é habilitada por padrão para componentes interativos.

A navegação interna para roteamento interativo não envolve a solicitação de novo conteúdo de página do servidor. Portanto, a pré-renderização não ocorre para solicitações de página internas, inclusive para navegação aprimorada. Para obter mais informações, veja Roteamento estático versus interativo, Roteamento interativo e pré-renderização , e Navegação aprimorada e manipulação de formulários .

A desativação da pré-renderização usando as técnicas a seguir só tem efeito para os modos de renderização de nível superior. Se um componente pai especificar um modo de renderização, as configurações de pré-renderização de seus filhos serão ignoradas. Esse comportamento está sob investigação para possíveis alterações com o lançamento do .NET 10 em novembro de 2025.

Para desativar a pré-renderização de uma instância de componente , passe o sinalizador prerender com um valor de false no modo de renderização.

  • <... @rendermode="new InteractiveServerRenderMode(prerender: false)" />
  • <... @rendermode="new InteractiveWebAssemblyRenderMode(prerender: false)" />
  • <... @rendermode="new InteractiveAutoRenderMode(prerender: false)" />

Para desativar a pré-renderização em uma definição de componente :

  • @rendermode @(new InteractiveServerRenderMode(prerender: false))
  • @rendermode @(new InteractiveWebAssemblyRenderMode(prerender: false))
  • @rendermode @(new InteractiveAutoRenderMode(prerender: false))

Para desativar a pré-renderização para todo o aplicativo, indique o modo de renderização no componente interativo de nível mais alto na hierarquia de componentes do aplicativo que não seja um componente raiz.

Para aplicativos baseados no modelo de projeto Blazor Web App, um modo de renderização atribuído ao aplicativo inteiro é especificado onde o componente Routes é usado no componente App (Components/App.razor). O exemplo a seguir define o modo de renderização do aplicativo como Interactive Server com a pré-renderização desabilitada:

razor
<Routes @rendermode="new InteractiveServerRenderMode(prerender: false)" />

Além disso, desative a pré-renderização para o componente HeadOutlet no componente App:

razor
<HeadOutlet @rendermode="new InteractiveServerRenderMode(prerender: false)" />

Não há suporte para tornar um componente raiz, como o componente App, interativo com a diretiva @rendermode na parte superior do arquivo de definição do componente raiz (.razor). Portanto, a pré-renderização não pode ser desabilitada diretamente pelo componente App.

Renderização estática do lado servidor (SSR estático)

Os componentes usam renderização estática do lado do servidor (SSR estático). O componente é renderizado no fluxo de resposta e a interatividade não está ativada.

No exemplo a seguir, não há designação para o modo de renderização do componente, portanto, o componente herda seu modo de renderização de seu pai. Como nenhum componente ancestral especifica um modo de renderização, o componente a seguir é renderizado estaticamente no servidor. O botão não é interativo e não chama o método UpdateMessage quando selecionado. O valor de message não é alterado e o componente não é reexibido em resposta a eventos da interface.

RenderMode1.razor:

razor
@page "/render-mode-1"

<button @onclick="UpdateMessage">Click me</button> @message

@code {
    private string message = "Not updated yet.";

    private void UpdateMessage()
    {
        message = "Somebody updated me!";
    }
}

Se estiver usando o componente anterior localmente em um Blazor Web App, coloque o componente na pasta Components/Pages do projeto de servidor. O projeto de servidor é o projeto da solução com um nome que não termina em .Client. Quando o aplicativo estiver em execução, navegue até /render-mode-1 na barra de endereço do navegador.

Durante o SSR estático, as solicitações de página de componente Razor são processadas pelo processamento de solicitações de pipeline de middleware ASP.NET Core do lado do servidor para roteamento e autorização. Os recursos dedicados ao Blazor para encaminhamento e autorização não estão operacionais porque durante o processamento de pedidos no lado do servidor, os componentes de Razor não são renderizados. Blazor recursos do roteador no componente Routes que não estão disponíveis durante o SSR estático incluem a exibição:

Se o aplicativo exibir interatividade no nível raiz, o processamento de solicitações ASP.NET Core do lado do servidor não estará envolvido após o SSR estático inicial, o que significa que os recursos de Blazor anteriores funcionarão conforme o esperado.

Navegação aprimorada com SSR estático requer atenção especial ao carregar JavaScript. Para obter mais informações, consulte ASP.NET Core Blazor JavaScript com renderização estática do lado do servidor (SSR estático).

Renderização interativa do lado do servidor (SSR interativo)

A renderização interativa do lado do servidor (SSR interativo) renderiza o componente a partir do servidor de forma interativa usando Blazor Server. As interações do usuário são tratadas através de uma conexão em tempo real com o navegador. A conexão de circuito é estabelecida quando o componente Servidor é renderizado.

No exemplo a seguir, o modo de renderização é definido como SSR interativo adicionando @rendermode InteractiveServer à definição do componente. O botão chama o método UpdateMessage quando selecionado. O valor de message é alterado e o componente é reprocessado para atualizar a mensagem na interface do usuário.

RenderMode2.razor:

razor
@page "/render-mode-2"
@rendermode InteractiveServer

<button @onclick="UpdateMessage">Click me</button> @message

@code {
    private string message = "Not updated yet.";

    private void UpdateMessage()
    {
        message = "Somebody updated me!";
    }
}

Se estiver usando o componente anterior em um Blazor Web App, coloque o componente na pasta Components/Pages do projeto de servidor. O projeto de servidor é o projeto da solução com um nome que não termina em .Client. Quando o aplicativo estiver em execução, navegue até /render-mode-2 na barra de endereço do navegador.

Renderização do lado do cliente (CSR)

A renderização do lado do cliente (CSR) renderiza o componente interativamente no cliente usando Blazor WebAssembly. O tempo de execução do .NET e o pacote de aplicativos são baixados e armazenados em cache quando o componente WebAssembly é inicialmente renderizado. Os componentes que usam CSR devem ser criados a partir de um projeto de cliente separado que configura o host Blazor WebAssembly.

No exemplo a seguir, o modo de renderização é definido como CSR com @rendermode InteractiveWebAssembly. O botão chama o método UpdateMessage quando selecionado. O valor de message é alterado e o componente é reprocessado para atualizar a mensagem na interface do usuário.

RenderMode3.razor:

razor
@page "/render-mode-3"
@rendermode InteractiveWebAssembly

<button @onclick="UpdateMessage">Click me</button> @message

@code {
    private string message = "Not updated yet.";

    private void UpdateMessage()
    {
        message = "Somebody updated me!";
    }
}

Se estiver usando o componente anterior localmente em um Blazor Web App, coloque o componente na pasta Pages do projeto cliente. O projeto cliente é o projeto da solução com um nome que termina em .Client. Quando o aplicativo estiver em execução, navegue até /render-mode-3 na barra de endereço do navegador.

Renderização automática (automática)

A renderização automática (Auto) determina como renderizar o componente em tempo de execução. O componente é inicialmente renderizado com renderização interativa do lado do servidor (SSR interativo) usando o modelo de hospedagem Blazor Server. O tempo de execução do .NET e o pacote de aplicativos são baixados para o cliente em segundo plano e armazenados em cache para que possam ser usados em visitas futuras.

O modo de renderização automática nunca altera dinamicamente o modo de renderização de um componente já na página. O modo de renderização automática toma uma decisão inicial sobre qual tipo de interatividade usar para um componente, em seguida, o componente mantém esse tipo de interatividade enquanto estiver na página. Um fator nessa decisão inicial é considerar se já existem componentes na página com interatividade WebAssembly/Server. O modo automático prefere selecionar um modo de renderização que corresponda ao modo de renderização dos componentes interativos existentes. A razão pela qual o modo automático prefere usar um modo de interatividade existente é evitar a introdução de um novo tempo de execução interativo que não compartilha o estado com o tempo de execução existente.

Os componentes que usam o modo de renderização automática devem ser criados a partir de um projeto cliente separado que configura o host Blazor WebAssembly.

No exemplo a seguir, o componente é interativo durante todo o processo. O botão chama o método UpdateMessage quando selecionado. O valor de message é alterado e o componente é reprocessado para atualizar a mensagem na interface do usuário. Inicialmente, o componente é renderizado interativamente do servidor, mas em visitas subsequentes ele é renderizado do cliente depois que o tempo de execução do .NET e o pacote de aplicativos são baixados e armazenados em cache.

RenderMode4.razor:

razor
@page "/render-mode-4"
@rendermode InteractiveAuto

<button @onclick="UpdateMessage">Click me</button> @message

@code {
    private string message = "Not updated yet.";

    private void UpdateMessage()
    {
        message = "Somebody updated me!";
    }
}

Se estiver usando o componente anterior localmente em um Blazor Web App, coloque o componente na pasta Pages do projeto cliente. O projeto cliente é o projeto da solução com um nome que termina em .Client. Quando o aplicativo estiver em execução, navegue até /render-mode-4 na barra de endereço do navegador.

Propagação do modo de renderização

Os modos de renderização propagam-se para baixo na hierarquia de componentes.

Regras para aplicar modos de renderização:

  • O modo de renderização padrão é Estático.
  • Os modos de renderização Interactive Server (InteractiveServer), Interactive WebAssembly (InteractiveWebAssembly) e Interactive Auto (InteractiveAuto) podem ser usados a partir de um componente, incluindo o uso de diferentes modos de renderização para componentes irmãos.
  • Não é possível mudar para um modo de renderização interativo diferente num componente filho. Por exemplo, um componente Server não pode ser filho de um componente WebAssembly.
  • Os parâmetros passados para um componente filho interativo de um pai estático devem ser serializáveis em JSON. Isso significa que você não pode passar fragmentos de renderização ou conteúdo filho de um componente pai estático para um componente filho interativo.

Os exemplos a seguir usam um componente SharedMessage que é não roteável e não de página. O componente SharedMessage agnóstico em relação ao modo de renderização não aplica um modo de renderização quando usado com uma diretiva @attribute. Se você estiver testando esses cenários com um Blazor Web App, coloque o componente a seguir na pasta Components do aplicativo.

SharedMessage.razor:

razor
<p>@Greeting</p>

<button @onclick="UpdateMessage">Click me</button> @message

<p>@ChildContent</p>

@code {
    private string message = "Not updated yet.";

    [Parameter]
    public RenderFragment? ChildContent { get; set; }

    [Parameter]
    public string Greeting { get; set; } = "Hello!";

    private void UpdateMessage()
    {
        message = "Somebody updated me!";
    }
}

Herança do modo de renderização

Se o componente SharedMessage for colocado em um componente pai renderizado estaticamente, o componente SharedMessage também será renderizado estaticamente e não será interativo. O botão não chama UpdateMessagee a mensagem não é atualizada.

RenderMode5.razor:

razor
@page "/render-mode-5"

<SharedMessage />

Se o componente SharedMessage for colocado em um componente que define o modo de renderização, ele herdará o modo de renderização aplicado.

No exemplo a seguir, o componente SharedMessage é interativo em uma conexão SignalR com o cliente. O botão aciona UpdateMessagee a mensagem é atualizada.

RenderMode6.razor:

razor
@page "/render-mode-6"
@rendermode InteractiveServer

<SharedMessage />

Componentes filho com diferentes modos de renderização

No exemplo a seguir, ambos os componentes SharedMessage são pré-renderizados e aparecem quando a página é exibida no navegador.

  • O primeiro componente SharedMessage com renderização interativa do lado do servidor (SSR interativa) é interativo depois que o circuito de Blazor de SignalRé estabelecido.
  • O segundo componente SharedMessage com renderização do lado do cliente (CSR) é interativo após o pacote de aplicativos Blazor é baixado e o tempo de execução do .NET está ativo no cliente.

RenderMode7.razor:

razor
@page "/render-mode-7"

<SharedMessage @rendermode="InteractiveServer" />
<SharedMessage @rendermode="InteractiveWebAssembly" />

Componente filho com um parâmetro serializável

O exemplo a seguir demonstra um componente filho interativo que usa um parâmetro. Os parâmetros devem ser serializáveis.

RenderMode8.razor:

razor
@page "/render-mode-8"

<SharedMessage @rendermode="InteractiveServer" Greeting="Welcome!" />

Não há suporte para parâmetros de componentes não serializáveis, como conteúdo filho ou um fragmento de renderização. No exemplo a seguir, passar conteúdo filho para o componente SharedMessage resulta em um erro de tempo de execução.

RenderMode9.razor:

razor
@page "/render-mode-9"

<SharedMessage @rendermode="InteractiveServer">
    Child content
</SharedMessage>

Erro:

System.InvalidOperationException: Não é possível passar o parâmetro 'ChildContent' para o componente 'SharedMessage' com rendermode 'InteractiveServerRenderMode'. Isso ocorre porque o parâmetro é do tipo delegado 'Microsoft.AspNetCore.Components.RenderFragment', que é um código arbitrário e não pode ser serializado.

Para contornar a limitação anterior, envolva o componente filho em outro componente que não tenha o parâmetro. Esta é a abordagem adotada no modelo de projeto Blazor Web App com o componente Routes (Components/Routes.razor) para encapsular o componente Router.

WrapperComponent.razor:

razor
<SharedMessage>
    Child content
</SharedMessage>

RenderMode10.razor:

razor
@page "/render-mode-10"

<WrapperComponent @rendermode="InteractiveServer" />

No exemplo anterior:

  • O conteúdo filho é passado para o componente SharedMessage sem gerar um erro em tempo de execução.
  • O componente SharedMessage é renderizado interativamente no servidor.

Componente filho com um modo de renderização diferente do pai

Não tente aplicar um modo de renderização interativo diferente ao de um componente filho do modo de renderização do componente pai.

O componente a seguir resulta em um erro de tempo de execução quando o componente é renderizado:

RenderMode11.razor:

razor
@page "/render-mode-11"
@rendermode InteractiveServer

<SharedMessage @rendermode="InteractiveWebAssembly" />

Erro:

Cannot create a component of type 'BlazorSample.Components.SharedMessage' because its render mode 'Microsoft.AspNetCore.Components.Web.InteractiveWebAssemblyRenderMode' is not supported by Interactive Server rendering.

Páginas SSR estáticas em um aplicativo interativo

Há casos em que a especificação do aplicativo exige que os componentes adotem a renderização estática do lado do servidor (SSR estático) e só sejam executados no servidor, enquanto o restante do aplicativo usa um modo de renderização interativo.

Essa abordagem só é útil quando o aplicativo tem páginas específicas que não podem funcionar com renderização interativa de servidor ou WebAssembly. Por exemplo, adote essa abordagem para páginas que dependem de leitura/gravação de cookies HTTP e só podem funcionar em um ciclo de solicitação/resposta em vez de renderização interativa. Para páginas que trabalham com renderização interativa, você não deve forçá-las a usar SSR estático, pois é menos eficiente e menos responsivo para o usuário final.

Marque qualquer página de componente Razor com o atributo [ExcludeFromInteractiveRouting] atribuído com a diretiva @attributeRazor:

razor
@attribute [ExcludeFromInteractiveRouting]

A aplicação do atributo faz com que a saída da navegação para a página ocorra a partir do roteamento interativo . A navegação de entrada é forçada a realizar uma recarga de página inteira em vez de resolver a página por meio de roteamento interativo. A recarga de página inteira força o componente raiz de nível superior, normalmente o componente App (App.razor), a renderizar novamente a partir do servidor, permitindo que o aplicativo alterne para um modo de renderização de nível superior diferente.

O método de extensão RazorComponentsEndpointHttpContextExtensions.AcceptsInteractiveRouting permite que o componente detete se o atributo [ExcludeFromInteractiveRouting] é aplicado à página atual.

No componente App, use o padrão no exemplo a seguir:

  • As páginas que não estão anotadas com o atributo [ExcludeFromInteractiveRouting] recorrem ao modo de renderização InteractiveServer com interatividade global. Você pode substituir InteractiveServer por InteractiveWebAssembly ou InteractiveAuto para especificar um modo de renderização global padrão diferente.
  • As páginas anotadas com o atributo [ExcludeFromInteractiveRouting] adotam SSR estático (PageRenderMode é atribuído null).
razor
<!DOCTYPE html>
<html>
<head>
    ...
    <HeadOutlet @rendermode="@PageRenderMode" />
</head>
<body>
    <Routes @rendermode="@PageRenderMode" />
    ...
</body>
</html>

@code {
    [CascadingParameter]
    private HttpContext HttpContext { get; set; } = default!;

    private IComponentRenderMode? PageRenderMode
        => HttpContext.AcceptsInteractiveRouting() ? InteractiveServer : null;
}

Uma alternativa ao uso do método de extensão RazorComponentsEndpointHttpContextExtensions.AcceptsInteractiveRouting é ler os metadados do endpoint manualmente usando HttpContext.GetEndpoint()?.Metadata.

Há duas abordagens que podem ser adotadas para um controle fino dos modos de renderização, cada uma das quais é descrita nas seguintes subseções:

  • Área (pasta) de componentes SSR estáticos: Você tem uma área (pasta) do aplicativo com componentes que devem adotar SSR estático e compartilhar o mesmo prefixo de caminho de rota. O aplicativo controla o modo de renderização globalmente definindo o modo de renderização no componente Routes no componente App com base no caminho para a pasta.

  • Componentes SSR estáticos espalhados pelo aplicativo: Você tem componentes espalhados pelo aplicativo em vários locais que devem adotar SSR estático e só são executados no servidor. Os componentes estáticos exclusivos de SSR não estão numa única pasta e não compartilham um prefixo comum no caminho de rota. O aplicativo controla o modo de renderização por componente, definindo o modo de renderização com a diretiva @rendermode em instâncias de componentes. A reflexão é usada no componente App para definir o modo de renderização no componente Routes.

Em ambos os casos, o componente que deve adotar SSR estático também precisa forçar uma recarga completa da página.

Os exemplos a seguir usam o parâmetro HttpContext em cascata para determinar se a página é renderizada estaticamente. Um nullHttpContext indica que o componente está renderizando interativamente, o que é útil como um sinal no código do aplicativo para disparar uma recarga de página inteira.

Área (pasta) de componentes SSR estáticos

Para obter um exemplo da abordagem nesta seção, consulte o BlazorWebAppAreaOfStaticSsrComponents aplicativo de exemplo. A técnica descrita nesta seção é mais apropriada para 8.0 Blazor Web Apps, mas a amostra é implementada em 9.0, usando recursos Blazor que simplificam a demonstração de como a abordagem funciona.

A abordagem descrita nesta subseção é usada pelo modelo de projeto Blazor Web App com interatividade global.

Uma área (pasta) do aplicativo contém os componentes que devem adotar SSR estático e ser executados apenas no servidor. Os componentes na pasta compartilham o mesmo prefixo de caminho de rota. Por exemplo, os componentes IdentityRazor do modelo de projeto Blazor Web App estão na pasta Components/Account/Pages e compartilham o prefixo do caminho raiz /account.

O aplicativo também contém um arquivo _Imports.razor aplicado automaticamente aos componentes SSR estáticos na pasta Components, que aplica um layout personalizado.

Components/Account/_Imports.razor:

razor
@using BlazorSample.Components.Account.Shared
@layout AccountLayout

A pasta Shared mantém o componente de layout AccountLayout. O componente faz uso de HttpContext para determinar se o componente adotou SSR estático. Por exemplo, os componentes Identity devem ser renderizados no servidor com SSR estático porque eles configuram os cookies Identity. Se o valor de HttpContext for null, o componente está a ser renderizado interativamente e será feita uma recarga total da página chamando NavigationManager.Refresh com forceLoad definido como true. Isso força uma rerenderização completa da página usando SSR estático.

Components/Account/Shared/AccountLayout.razor:

razor
@inherits LayoutComponentBase
@layout BlazorSample.Components.Layout.MainLayout
@inject NavigationManager Navigation

@if (HttpContext is null)
{
    <p>Loading...</p>
}
else
{
    @Body
}

@code {
    [CascadingParameter]
    private HttpContext? HttpContext { get; set; }

    protected override void OnParametersSet()
    {
        if (HttpContext is null)
        {
            Navigation.Refresh(forceReload: true);
        }
    }
}

Nota

No modelo de projeto Blazor Web App para cenários de autenticação, existe um segundo ficheiro de layout (ManageLayout.razor na pasta Components/Account/Shared) destinado aos componentes Identity da pasta Components/Account/Pages/Manage. A pasta Manage tem o seu próprio ficheiro _Imports.razor para aplicar o ManageLayout aos componentes na pasta. Em seus próprios aplicativos, usar arquivos _Imports.razor aninhados é uma abordagem útil para aplicar layouts personalizados a grupos de páginas.

No componente App, qualquer solicitação para um componente na pasta Account aplica um modo de renderização null, que impõe SSR estático. Outras solicitações de componentes recebem uma aplicação global do modo de renderização SSR interativo (InteractiveServer).

Importante

A aplicação do modo de renderização null nem sempre impõe o SSR estático. Acontece que ele se comporta dessa maneira usando a abordagem mostrada nesta seção.

Um modo de renderização null é efetivamente igual a não especificar um modo de renderização, fazendo com que o componente herde o modo de renderização do seu pai. Nesse caso, o componente App é renderizado usando SSR estático, portanto, um modo de renderização null resulta no componente Routes herdando SSR estático do componente App. Se um modo de renderização nulo for especificado para um componente filho cujo pai usa um modo de renderização interativo, o filho herda o mesmo modo de renderização interativo.

Components/App.razor:

razor
<Routes @rendermode="RenderModeForPage" />

...

@code {
    [CascadingParameter]
    private HttpContext HttpContext { get; set; } = default!;

    private IComponentRenderMode? RenderModeForPage => 
        HttpContext.Request.Path.StartsWithSegments("/account")
            ? null
            : {INTERACTIVE RENDER MODE};
}

No código anterior, altere o espaço reservado {INTERACTIVE RENDER MODE} para o valor apropriado, dependendo se o restante da aplicação deve adotar a renderização global de InteractiveServer, InteractiveWebAssembly, ou de InteractiveAuto.

Os componentes que devem adotar SSR estático na pasta Account não são necessários para definir o layout, que é aplicado por meio do arquivo _Imports.razor. Os componentes não definem um modo de renderização porque devem renderizar com SSR estático. Os componentes na pasta Account não precisam de mais nenhuma ação para aplicar o SSR estático.

Componentes SSR estáticos espalhados pelo aplicativo

Para obter um exemplo da abordagem nesta seção, consulte o BlazorWebAppSpreadOutStaticSsrComponents aplicativo de exemplo. A técnica descrita nesta seção é mais apropriada para 8.0 Blazor Web Apps, mas a amostra é implementada em 9.0 usando recursos Blazor que simplificam a demonstração de como a abordagem funciona.

Na subseção anterior, a aplicação controla o modo de renderização dos componentes ao definir globalmente o modo de renderização no componente App. Como alternativa, o componente App também pode adotar modos de renderização por componente para definir o modo de renderização, o que permite que componentes espalhados pelo aplicativo imponham a adoção de SSR estático. Esta subsecção descreve a abordagem.

O aplicativo tem um layout personalizado que pode ser aplicado aos componentes ao redor do aplicativo. Normalmente, um componente compartilhado para o aplicativo é colocado na pasta Components/Layout. O componente faz uso de HttpContext para determinar se o componente adotou SSR estático. Se o valor de HttpContext for null, o componente está a ser renderizado interativamente e será feita uma recarga total da página chamando NavigationManager.Refresh com forceLoad definido como true. Isso dispara uma solicitação ao servidor para o componente.

Components/Layout/StaticSsrLayout.razor:

razor
@inherits LayoutComponentBase
@layout MainLayout
@inject NavigationManager Navigation

@if (HttpContext is null)
{
    <p>Loading...</p>
}
else
{
    @Body
}

@code {
    [CascadingParameter]
    private HttpContext? HttpContext { get; set; }

    protected override void OnParametersSet()
    {
        if (HttpContext is null)
        {
            Navigation.Refresh(forceReload: true);
        }
    }
}

No componente App, a reflexão é usada para definir o modo de renderização. Qualquer modo de renderização atribuído ao arquivo de definição de componente individual é aplicado ao componente Routes.

Components/App.razor:

razor
<Routes @rendermode="RenderModeForPage" />

...

@code {
    [CascadingParameter]
    private HttpContext HttpContext { get; set; } = default!;

    private IComponentRenderMode? RenderModeForPage =>
        HttpContext.GetEndpoint()?.Metadata.GetMetadata<RenderModeAttribute>()?
            .Mode;
}

Cada componente que deve adotar SSR estático define o layout personalizado e não especifica um modo de renderização. Não especificar um modo de renderização resulta em um valor null de RenderModeAttribute.Mode no componente App, que, por sua vez, não atribui nenhum modo de renderização à instância do componente Routes, impondo o uso de SSR estático.

Importante

A aplicação do modo de renderização null nem sempre impõe o SSR estático. Acontece que ele se comporta dessa maneira usando a abordagem mostrada nesta seção.

Um modo de renderização null é efetivamente igual a não especificar um modo de renderização, fazendo com que o componente herde o modo de renderização do seu pai. Nesse caso, o componente App é renderizado usando SSR estático, portanto, um modo de renderização null resulta no componente Routes herdando SSR estático do componente App. Se um modo de renderização nulo for especificado para um componente filho cujo pai usa um modo de renderização interativo, o filho herda o mesmo modo de renderização interativo.

Nada mais deve ser feito para que os componentes imponham SSR estático do que aplicar o layout personalizado sem definir um modo de renderização interativo:

razor
@layout BlazorSample.Components.Layout.StaticSsrLayout

Os componentes interativos à volta da aplicação evitam aplicar o layout SSR estático personalizado e apenas definem um modo de renderização interativo apropriado, que, após reflexão, no componente App é aplicado ao componente Routes:

razor
@rendermode {INTERACTIVE RENDER MODE}

No código anterior, altere o espaço reservado {INTERACTIVE RENDER MODE} para o valor apropriado, dependendo se o componente deve adotar a renderização InteractiveServer, a renderização InteractiveWebAssemblyou a renderização InteractiveAuto.

Os serviços do lado do cliente falham na resolução durante a pré-renderização

Supondo que a pré-renderização não esteja desabilitada para um componente ou para o aplicativo, um componente no projeto .Client é pré-renderizado no servidor. Como o servidor não tem acesso a serviços de Blazor do lado do cliente registrados, não é possível injetar esses serviços em um componente sem receber um erro de que o serviço não pode ser encontrado durante a pré-renderização.

Por exemplo, considere o seguinte componente Home no projeto .Client em um Blazor Web App com WebAssembly interativo global ou renderização automática interativa. O componente tenta injetar IWebAssemblyHostEnvironment para obter o nome do ambiente.

razor
@page "/"
@inject IWebAssemblyHostEnvironment Environment

<PageTitle>Home</PageTitle>

<h1>Home</h1>

<p>
    Environment: @Environment.Environment
</p>

Nenhum erro de tempo de compilação ocorre, mas ocorre um erro de tempo de execução durante a pré-renderização:

Não é possível fornecer um valor para a propriedade 'Environment' no tipo 'BlazorSample.Client.Pages.Home'. Não há nenhum serviço registrado do tipo 'Microsoft.AspNetCore.Components.WebAssembly.Hosting.IWebAssemblyHostEnvironment'.

Este erro ocorre porque o componente deve compilar e executar no servidor durante a pré-renderização, mas IWebAssemblyHostEnvironment não é um serviço registrado no servidor.

Se a aplicação não exigir o valor durante a pré-renderização, esse problema pode ser resolvido ao injetar IServiceProvider para obter o serviço em vez do tipo de serviço em si.

razor
@page "/"
@using Microsoft.AspNetCore.Components.WebAssembly.Hosting
@inject IServiceProvider Services

<PageTitle>Home</PageTitle>

<h1>Home</h1>

<p>
    <b>Environment:</b> @environmentName
</p>

@code {
    private string? environmentName;

    protected override void OnInitialized()
    {
        if (Services.GetService<IWebAssemblyHostEnvironment>() is { } env)
        {
            environmentName = env.Environment;
        }
    }
}

No entanto, a abordagem anterior não será útil se sua lógica exigir um valor durante a pré-renderização.

Você também pode evitar o problema se desabilitar a de pré-renderização para o componente, mas essa é uma medida extrema a ser tomada em muitos casos que podem não atender às especificações do componente.

Há três abordagens que você pode adotar para resolver esse cenário. Os seguintes estão listados do mais recomendado ao menos recomendado:

  • recomendados para serviços de estrutura partilhada: Para serviços de estrutura partilhada que não estão registrados no lado do servidor no projeto principal, registre os serviços no projeto principal para torná-los disponíveis durante a pré-renderização. Para obter um exemplo desse cenário, consulte as diretrizes para serviços de HttpClient em Chamar uma API da Web de um aplicativo ASP.NET Core Blazor.

  • recomendada para serviços fora da estrutura compartilhada: crie uma implementação de serviço personalizada para o serviço no servidor. Use o serviço normalmente em componentes interativos do projeto .Client. Para obter uma demonstração dessa abordagem, consulte ASP.NET Core Blazor environments.

  • Crie uma abstração de serviço e crie implementações para o serviço nos projetos .Client e servidor. Registe os serviços em cada projeto. Injete o serviço personalizado no componente.

  • Talvez você possa adicionar uma referência de pacote de projeto .Client a um pacote do lado do servidor e voltar a usar a API do lado do servidor ao pré-renderizar no servidor.

Descubra componentes de montagens adicionais

Devem ser expostas montagens adicionais à estrutura Blazor para descobrir componentes Razor enrutáveis em projetos referenciados. Para obter mais informações, consulte ASP.NET Core Blazor roteamento e navegação.

Fechamento de circuitos quando não há componentes restantes do Servidor Interativo

Os componentes do Servidor Interativo lidam com eventos da interface do usuário da Web usando uma conexão em tempo real com o navegador chamada circuito. Um circuito e seu estado associado são criados quando um componente raiz do Servidor Interativo é renderizado. O circuito é fechado quando não há componentes restantes do Servidor Interativo na página, o que libera recursos do servidor.

Modos de renderização abreviados personalizados

A diretiva @rendermode usa um único parâmetro que é uma instância estática do tipo IComponentRenderMode. O atributo de diretiva @rendermode pode usar qualquer instância de modo de renderização, estática ou não. A estrutura Blazor fornece a classe estática RenderMode alguns modos de renderização predefinidos para conveniência, mas você pode criar o seu próprio.

Normalmente, um componente usa a seguinte diretiva @rendermode para desativar de pré-renderização:

razor
@rendermode @(new InteractiveServerRenderMode(prerender: false))

No entanto, considere o exemplo a seguir que cria um modo de renderização interativo do lado do servidor sem pré-renderização por meio do arquivo _Imports do aplicativo (Components/_Imports.razor):

C#
public static IComponentRenderMode InteractiveServerWithoutPrerendering { get; } = 
    new InteractiveServerRenderMode(prerender: false);

Use o modo de renderização abreviada em componentes em toda a pasta Components:

razor
@rendermode InteractiveServerWithoutPrerendering

Como alternativa, uma única instância de componente pode definir um modo de renderização personalizado por meio de um campo privado:

razor
@rendermode interactiveServerWithoutPrerendering

...

@code {
    private static IComponentRenderMode interactiveServerWithoutPrerendering = 
        new InteractiveServerRenderMode(prerender: false);
}

Neste momento, a abordagem do modo de renderização abreviada provavelmente só é útil para reduzir a verbosidade ao especificar o sinalizador prerender. A abordagem abreviada pode ser mais útil no futuro se sinalizadores adicionais ficarem disponíveis para renderização interativa e você quiser criar modos de renderização abreviada com diferentes combinações de sinalizadores.

Injeção de serviço através de um arquivo de importação de nível superior (_Imports.razor)

Esta seção aplica-se apenas a Blazor Web Apps.

Um arquivo de importação de nível superior na pasta Components (Components/_Imports.razor) injeta suas referências em todos os componentes na hierarquia de pastas, que inclui o componente App (App.razor). O componente App é sempre renderizado de forma estática, mesmo que a pré-renderização de um componente de página esteja desabilitada. Portanto, injetar serviços por meio do arquivo de importações de nível superior resulta na resolução de duas instâncias do serviço em componentes de página.

Para resolver esse cenário, injete o serviço em um novo arquivo de importações colocado na pasta Pages (Components/Pages/_Imports.razor). A partir dessa localização, o serviço só é processado uma vez nos componentes da página.

Recursos adicionais