Compartir vía


Modos de representación de ASP.NET Core Blazor

En este artículo se explica el control de la representación de componentes Razor en Blazor Web App, ya sea en tiempo de compilación o runtime.

Esta guía no se aplica a las aplicaciones Blazor WebAssembly independientes. Las aplicaciones Blazor WebAssembly solo se representan en el cliente mediante un entorno de ejecución basado en WebAssembly del lado cliente y no tienen ningún concepto de modo de representación. Si se aplica un modo de representación a un componente de una aplicación Blazor WebAssembly, la designación del modo de representación no influye en la representación del componente.

Modos de representación

Cada componente de una Blazor Web App adopta un modo de representación para determinar el modelo de hospedaje que usa, dónde se representa y si es interactivo o no.

En la tabla siguiente se muestran los modos de representación disponibles para representar componentes Razor en una Blazor Web App. Para aplicar un modo de representación a un componente, use la directiva @rendermode en la instancia del componente o en la definición del componente. Más adelante en este artículo, se muestran ejemplos para cada escenario de modo de representación.

Nombre Descripción Ubicación de representación Interactive
Servidor estático Representación estática del lado servidor (SSR estática) Servidor No
Servidor interactivo Representación interactiva del lado servidor (SSR interactiva) mediante Blazor Server. Server
WebAssembly interactivo Representación del lado cliente (CSR) mediante Blazor WebAssembly†. Remoto
Automático interactivo SSR interactiva mediante Blazor Server inicialmente y, a continuación, CSR en las visitas posteriores después de descargar la agrupación de Blazor. Servidor y, a continuación, cliente

†Se supone que la representación del lado cliente (CSR) es interactiva. La "representación interactiva del lado cliente" y la "CSR interactiva " no se usan en el sector ni en la documentación de Blazor.

La representación previa está habilitada de forma predeterminada para componentes interactivos. Más adelante en este artículo se proporcionan instrucciones sobre el control de la representación previa. Para conocer la terminología general del sector sobre los conceptos de representación de cliente y servidor, consulte los aspectos básicos de Blazor con ASP.NET Core.

En los ejemplos siguientes se muestra cómo establecer el modo de representación del componente con algunas características básicas del componente Razor.

Para probar los comportamientos del modo de representación localmente, puedes colocar los siguientes componentes en una aplicación creada a partir de la plantilla de proyecto de Blazor Web App. Al crear la aplicación, seleccione las opciones en los menús desplegables (Visual Studio) o aplique las opciones de la CLI (.NET CLI) para habilitar la interactividad del lado servidor y del lado cliente. Para obtener instrucciones sobre cómo crear una Blazor Web App, consulta Herramientas para ASP.NET Core Blazor.

Habilitar la compatibilidad con modos de representación interactivos

Una Blazor Web App debe configurarse para admitir modos de representación interactivos. Las extensiones siguientes se aplican automáticamente a las aplicaciones creadas a partir de la plantilla de proyecto de Blazor Web App durante la creación de la aplicación. Los componentes individuales siempre deben declarar su modo de representación según la sección Modos de representación una vez que los puntos de conexión y los servicios del componente estén configurados en el archivo Program de la aplicación.

Los servicios de los componentes Razor se agregan mediante una llamada a AddRazorComponents.

Extensiones del generador de componentes:

MapRazorComponents detecta los componentes disponibles y especifica el componente raíz de la aplicación (el primer componente cargado), que de forma predeterminada es el componente App (App.razor).

Extensiones del generador de convención de punto de conexión:

Nota:

Para obtener orientación sobre la ubicación de la API en los ejemplos siguientes, inspecciona el archivo Program de una aplicación generada a partir de la plantilla de proyecto de Blazor Web App. Para obtener instrucciones sobre cómo crear una Blazor Web App, consulta Herramientas para ASP.NET Core Blazor.

Ejemplo 1: la siguiente API de archivo Program agrega servicios y configuración para habilitar la SSR interactiva:

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

Ejemplo 2: la siguiente API de archivo Program agrega servicios y configuración para habilitar el modo de representación WebAssembly interactivo:

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

Ejemplo 3: la siguiente API de archivo Program agrega servicios y configuración para habilitar los modos de representación Servidor interactivo, WebAssembly interactivo y Automático interactivo:

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

Blazor usa el modelo de hospedaje Blazor WebAssembly para descargar y ejecutar componentes que usan el modo de representación WebAssembly interactivo. Se requiere un proyecto de cliente independiente para configurar el hospedaje Blazor WebAssembly para estos componentes. El proyecto de cliente contiene el código de inicio del host Blazor WebAssembly y configura el entorno de ejecución de .NET para ejecutarse en un explorador. La plantilla de Blazor Web App agrega este proyecto de cliente por ti al seleccionar la opción para habilitar la interactividad de WebAssembly. Los componentes que usen el modo de representación WebAssembly interactivo deben compilarse a partir del proyecto de cliente, por lo que se incluyen en el lote de aplicaciones descargado.

Aplicar un modo de representación a una instancia de componente

Para aplicar un modo de representación a una instancia de componente, usa el atributo de directiva @rendermodeRazor donde se usa el componente.

En el ejemplo siguiente, la representación interactiva del lado servidor (SSR interactiva) se aplica a la instancia del componente Dialog:

<Dialog @rendermode="InteractiveServer" />

Nota:

Las plantillas Blazor incluyen una directiva estática using para RenderMode en el archivo de _Imports la aplicación (Components/_Imports.razor) para una sintaxis más corta @rendermode:

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

Sin la directiva anterior, los componentes deben especificar la clase estática RenderMode en la sintaxis @rendermode:

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

También puedes hacer referencia a instancias del modo de representación personalizado creadas directamente con la configuración personalizada. Para obtener más información, consulta la sección Modos de representación abreviados personalizados más adelante en este artículo.

Aplicar un modo de representación a una definición de componente

Para especificar el modo de representación de un componente como parte de su definición, use la directiva @rendermodeRazor y el atributo de modo de representación correspondiente.

@page "..."
@rendermode InteractiveServer

La aplicación de un modo de representación a una definición de componente se usa normalmente al aplicar un modo de representación a una página específica. Las páginas enrutables usan el mismo modo de representación que el componente Router que ha representado la página.

Técnicamente, @rendermode es una Razordirectiva y un Razoratributo de directiva. La semántica es similar, pero hay diferencias. La directiva @rendermode está en la definición del componente, por lo que la instancia del modo de representación a la que se hace referencia debe ser estática. El atributo de directiva @rendermode puede tomar cualquier instancia del modo de representación.

Nota:

Los autores de componentes deben evitar acoplar la implementación de un componente a un modo de representación específico. En su lugar, los autores de componentes normalmente deben diseñar componentes para admitir cualquier modo de representación o modelo de hospedaje. La implementación de un componente debe evitar suposiciones sobre dónde se ejecuta (servidor o cliente) y debe degradarse correctamente cuando se representa estáticamente. Es posible que sea necesario especificar el modo de representación en la definición del componente si no se crea una instancia del componente directamente (por ejemplo, con un componente de página enrutable) o para especificar un modo de representación para todas las instancias del componente.

Aplicación de un modo de representación en toda la aplicación

Para establecer el modo de representación para toda la aplicación, indica el modo de representación en el componente interactivo de nivel más alto de la jerarquía de componentes de la aplicación que no es un componente raíz.

Nota:

No se admite la creación de un componente raíz interactivo, como el componente App. Por tanto, el componente App no puede establecer directamente el modo de representación para toda la aplicación.

En el caso de las aplicaciones basadas en la plantilla de proyecto de Blazor Web App, suele especificarse un modo de representación asignado a toda la aplicación donde se usa el componente Routes en el componente App (Components/App.razor):

<Routes @rendermode="InteractiveServer" />

El componente Router propaga su modo de representación a las páginas que enruta.

Normalmente, también debes establecer el mismo modo de representación interactivo en el componente HeadOutlet, que también se encuentra en el componente App de una Blazor Web App generada a partir de la plantilla del proyecto:

<HeadOutlet @rendermode="InteractiveServer" />

En el caso de las aplicaciones que adoptan un modo de representación interactivo del lado cliente (WebAssembly o Automático) y habilitan el modo de representación para toda la aplicación a través del componenteRoutes:

  • Coloca o mueve los archivos de diseño y navegación de la carpeta Components/Layout de la aplicación del servidor a la carpeta Layout del proyecto .Client. Crea una carpeta Layout en el proyecto .Client si todavía no existe.
  • Coloca o mueve los componentes de la carpeta Components/Pages de la aplicación del servidor a la carpeta Pages del proyecto .Client. Crea una carpeta Pages en el proyecto .Client si todavía no existe.
  • Coloca o mueve el componente Routes de la carpeta Components de la aplicación del servidor a la carpeta raíz del proyecto .Client.

Para habilitar la interactividad global al crear una Blazor Web App:

  • Visual Studio: establezca la lista desplegable Ubicación de interactividad en Global.
  • CLI de .NET: usar la opción -ai|--all-interactive.

Para más información, vea Herramientas para ASP.NET Core Blazor.

Aplicar un modo de representación mediante programación

Las propiedades y los campos pueden asignar modos de representación.

El segundo enfoque descrito en esta sección, establecer el modo de representación por instancia de componente, es especialmente útil cuando la especificación de la aplicación llama a uno o varios componentes para adoptar SSR estática en una aplicación interactiva globalmente. Este escenario se trata en la sección páginas de SSR estática de una aplicación interactiva globalmente más adelante en este artículo.

Establecimiento del modo de representación por definición de componente

Una definición de componente puede definir un modo de representación a través de un campo privado:

@rendermode pageRenderMode

...

@code {
    private static IComponentRenderMode pageRenderMode = InteractiveServer;
}

Establecimiento del modo de representación por instancia de componente

En el ejemplo siguiente, se aplica la representación interactiva del lado servidor (SSR interactiva) a cualquier solicitud.

<Routes @rendermode="PageRenderMode" />

...

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

Se proporciona información adicional sobre la propagación del modo de representación en la sección Propagación del modo de representación más adelante en este artículo. Las páginas de SSR estática de una aplicación interactiva globalmente muestran cómo usar el enfoque anterior para adoptar la SSR estática en una aplicación interactiva globalmente.

Detección de la ubicación de representación, interactividad y modo de representación asignado en tiempo de ejecución

Las propiedades ComponentBase.RendererInfo y ComponentBase.AssignedRenderMode permiten a la aplicación detectar detalles sobre la ubicación, la interactividad y el modo de representación asignado de un componente:

  • RendererInfo.Name devuelve la ubicación donde se ejecuta el componente:
    • Static: En el servidor (SSR) e incapaz de interactividad.
    • Server: En el servidor (SSR) y capaz de interactividad después de la representación previa.
    • WebAssembly: En el cliente (CSR) y capaz de interactividad después de la representación previa.
    • WebView: En el dispositivo nativo y capaz de interactividad después de la representación previa.
  • RendererInfo.IsInteractive Indica si el componente admite interactividad en el momento de la representación. El valor es true cuando se representa de forma interactiva o false al representar previamente o para SSR estático (Platform.Name de Static).
  • ComponentBase.AssignedRenderMode expone el modo de representación asignado del componente:
    • InteractiveServer para Interactive Server.
    • InteractiveAuto para Interactive Auto.
    • InteractiveWebAssembly para Interactive WebAssembly.

Los componentes usan estas propiedades para representar contenido en función de su ubicación o estado de interactividad. Por ejemplo, un formulario se puede deshabilitar durante la representación previa y habilitarse cuando el componente se vuelve interactivo:

<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;
        }
    }
}

En el ejemplo siguiente se muestra cómo representar el marcado para admitir la realización de una acción HTML normal si el componente se representa estáticamente:

@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>
}

En el ejemplo anterior:

  • Cuando el valor de AssignedRenderMode es null, el componente adopta SSR estático. Blazor control de eventos no funciona en un explorador con SSR estático, por lo que el componente envía un formulario (solicitud GET) con una cadena de consulta titleFilter establecida en el valor de <input> del usuario. El componente Movie (/movie) puede leer la cadena de consulta y procesar el valor de titleFilter para representar el componente con los resultados filtrados.
  • De lo contrario, el modo de representación es cualquiera de InteractiveServer, InteractiveWebAssembly, o InteractiveAuto. El componente es capaz de usar un delegado de controlador de eventos (FilterMovies) y el valor enlazado al elemento <input> (titleFilter) para filtrar películas de forma interactiva a través de la conexión de SignalR en segundo plano.

Ejemplos de documentación de Blazor para Blazor Web App

Cuando se usa Blazor Web App, la mayoría de los componentes de ejemplo de documentación de Blazor requieren interactividad para funcionar y demostrar los conceptos descritos en los artículos. Al probar un componente de ejemplo proporcionado por un artículo, asegúrese de que, o bien la aplicación adopta la interactividad global, o bien el componente adopta un modo de representación interactivo.

Representación previa

La representación previa es el proceso de representación inicial del contenido de la página en el servidor sin habilitar controladores de eventos para controles representados. El servidor genera la interfaz de usuario HTML de la página lo antes posible en respuesta a la solicitud inicial, lo que hace que la aplicación se sienta más sensible a los usuarios. La representación previa también puede mejorar la optimización del motor de búsqueda (SEO) mediante la representación del contenido de la respuesta HTTP inicial que los motores de búsqueda usan para calcular la clasificación de página.

La representación previa está habilitada de forma predeterminada para componentes interactivos.

La navegación interna para el enrutamiento interactivo no implica solicitar contenido de página nuevo desde el servidor. Por lo tanto, la representación previa no se produce para las solicitudes de página internas, incluidas las de navegación mejorada. Para obtener más información, consulte enrutamiento estático frente a interactivo, Enrutamiento interactivo y representación previa y Navegación mejorada y control de formularios.

Deshabilitar la representación previa mediante las siguientes técnicas solo surte efecto para los modos de representación de nivel superior. Si un componente primario especifica un modo de representación, se omite la configuración de representación previa de sus elementos secundarios. Este comportamiento está bajo investigación para posibles cambios con la versión de .NET 10 en noviembre de 2025.

Para deshabilitar la representación previa de una instancia de componente, pasa la marca prerender con un valor de false para representar el modo:

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

Para deshabilitar la representación previa en una definición de componente:

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

Para deshabilitar la representación previa para toda la aplicación, indica el modo de representación en el componente interactivo de nivel más alto de la jerarquía de componentes de la aplicación que no es un componente raíz.

En el caso de las aplicaciones basadas en la plantilla de proyecto de Blazor Web App, se especifica un modo de representación asignado a toda la aplicación donde se usa el componente Routes en el componente App (Components/App.razor): En el ejemplo siguiente se establece el modo de representación de la aplicación en Servidor interactivo con la representación previa deshabilitada:

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

Además, deshabilita la representación previa para el HeadOutletcomponente en el componente App:

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

No se admite la creación de un componente raíz, como el componente App, interactivo con la directiva @rendermode en la parte superior del archivo de definición del componente raíz (.razor). Por lo tanto, el componente App no puede deshabilitar la representación previa directamente.

Representación estática del lado servidor (SSR estática)

Los componentes usan la representación estática del lado servidor (SSR estática). El componente se representa en el flujo de respuesta y la interactividad no está habilitado.

En el ejemplo siguiente, no hay ninguna designación para el modo de representación del componente, de forma que el componente hereda su modo de representación del elemento primario. Como ningún componente antecesor especifica un modo de representación, el siguiente componente se representa estáticamente en el servidor. El botón no es interactivo y no llama al método UpdateMessage cuando se selecciona. El valor de message no cambia y el componente no se vuelve a representar en respuesta a los eventos de la interfaz de usuario.

RenderMode1.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!";
    }
}

Si usas el componente anterior localmente en una Blazor Web App, coloca el componente en la carpeta Components/Pages del proyecto de servidor. El proyecto de servidor es el proyecto de la solución con un nombre que no termina en .Client. Cuando se ejecute la aplicación, ve a /render-mode-1 en la barra de direcciones del explorador.

Durante la SSR estática, las solicitudes de página de componentes Razor se procesan en el procesamiento de solicitudes de canalización de middleware de ASP.NET Core del lado servidor para el enrutamiento y la autorización. Las características de Blazor dedicadas para el enrutamiento y la autorización no están operativas porque los componentes Razor no se representan durante el procesamiento de solicitudes del lado servidor. Las características del enrutador de Blazor en el componente Routes que no están disponibles durante la SSR estática incluyen la visualización de:

Si la aplicación muestra interactividad a nivel raíz, el procesamiento de solicitudes de ASP.NET Core del lado servidor no está implicado después de la SSR estática inicial, lo que significa que las características de Blazor anteriores funcionan según lo previsto.

La navegación mejorada con SSR estática requiere especial atención al cargar JavaScript. Para obtener más información, consulta ASP.NET Core Blazor JavaScript con representación estática del lado servidor.

Representación interactiva del lado servidor (SSR interactiva)

La representación interactiva del lado servidor (SSR interactiva) representa el componente de forma interactiva desde el servidor mediante Blazor Server. Las interacciones del usuario se controlan a través de una conexión en tiempo real con el explorador. La conexión del circuito se establece cuando se representa el componente Servidor.

En el ejemplo siguiente, el modo de representación se establece en SSR interactiva agregando @rendermode InteractiveServer a la definición del componente. El botón llama al método UpdateMessage cuando se selecciona. El valor de message cambia y el componente se vuelve a representar para actualizar el mensaje en la interfaz de usuario.

RenderMode2.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!";
    }
}

Si usa el componente anterior en , Blazor Web Appcoloque el componente en la carpeta del proyecto de Components/Pages servidor. El proyecto de servidor es el proyecto de la solución con un nombre que no termina en .Client. Cuando se ejecute la aplicación, vaya a /render-mode-2 en la barra de direcciones del explorador.

Representación del lado cliente (CSR)

La representación del lado cliente (CSR) representa el componente de forma interactiva en el cliente mediante Blazor WebAssembly. El entorno de ejecución de .NET y el lote de aplicaciones se descargan y almacenan en caché cuando el componente WebAssembly se representa inicialmente. Los componentes que usan la CSR deben compilarse a partir de un proyecto de cliente independiente que configure el host Blazor WebAssembly.

En el ejemplo siguiente, el modo de representación se configura en CSR con @rendermode InteractiveWebAssembly. El botón llama al método UpdateMessage cuando se selecciona. El valor de message cambia y el componente se vuelve a representar para actualizar el mensaje en la interfaz de usuario.

RenderMode3.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!";
    }
}

Si usas el componente anterior localmente en una Blazor Web App, coloca el componente en la carpeta Pages del proyecto de cliente. El proyecto de cliente es el proyecto de la solución con un nombre que termina en .Client. Cuando se ejecute la aplicación, ve a /render-mode-3 en la barra de direcciones del explorador.

Representación automática (Automático)

El modo de representación automática (Automático) determina cómo representar el componente en el runtime. El componente se representa inicialmente con la representación interactiva del lado servidor (SSR interactiva) mediante el modelo de hospedaje Blazor Server. El runtime de .NET y el lote de aplicaciones se descargan en el cliente en segundo plano y se almacenan en caché para que se puedan usar en futuras visitas.

El modo de representación Automático nunca cambia dinámicamente el modo de representación de un componente que ya está en la página. El modo de representación Automático toma una decisión inicial sobre el tipo de interactividad que se va a usar para un componente y, después, el componente mantiene ese tipo de interactividad mientras esté en la página. Un factor de esta decisión inicial es considerar si los componentes ya existen en la página con interactividad de WebAssembly/Server. El modo Automático prefiere seleccionar un modo de representación que coincida con el de los componentes interactivos existentes. La razón por la que el modo Automático prefiere usar un modo de interactividad existente es evitar la introducción de un nuevo runtime interactivo que no comparte el estado con el runtime existente.

Los componentes que usan el modo de representación Automático deben compilarse a partir de un proyecto de cliente independiente que configure el host Blazor WebAssembly.

En el ejemplo siguiente, el componente es interactivo en todo el proceso. El botón llama al método UpdateMessage cuando se selecciona. El valor de message cambia y el componente se vuelve a representar para actualizar el mensaje en la interfaz de usuario. Inicialmente, el componente se representa de forma interactiva desde el servidor, pero en las visitas posteriores se representa desde el cliente después de descargar y almacenar en caché el lote de aplicaciones y el runtime de .NET.

RenderMode4.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!";
    }
}

Si usas el componente anterior localmente en una Blazor Web App, coloca el componente en la carpeta Pages del proyecto de cliente. El proyecto de cliente es el proyecto de la solución con un nombre que termina en .Client. Cuando se ejecute la aplicación, ve a /render-mode-4 en la barra de direcciones del explorador.

Propagación del modo de representación

Los modos de representación propagan la jerarquía de componentes.

Reglas para aplicar modos de representación:

  • El modo de representación predeterminado es Estático.
  • Los modos de representación Servidor interactivo (InteractiveServer), WebAssembly interactivo (InteractiveWebAssembly) y Automático interactivo (InteractiveAuto) se pueden usar desde un componente, incluido el uso de diferentes modos de representación para los componentes del mismo nivel.
  • No se puede cambiar a otro modo de representación interactivo en un componente secundario. Por ejemplo, un componente Servidor no puede ser un elemento secundario de un componente WebAssembly.
  • Los parámetros pasados a un componente secundario interactivo a partir de un elemento primario estático deben ser serializables JSON. Esto significa que no se pueden pasar fragmentos de representación o contenido secundario de un componente primario estático a un componente secundario interactivo.

En los ejemplos siguientes se usa un componente SharedMessage que no es enrutable ni una página. El componente SharedMessage independiente del modo de representación no aplica un modo de representación con una directiva @attribute. Si vas a probar estos escenarios con una Blazor Web App, coloca el siguiente componente en la carpeta Components de la aplicación.

SharedMessage.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!";
    }
}

Herencia del modo de representación

Si el componente SharedMessage se coloca en un componente primario representado estáticamente, el componente SharedMessage también se representa estáticamente y no es interactivo. El botón no llama a UpdateMessage y el mensaje no se actualiza.

RenderMode5.razor:

@page "/render-mode-5"

<SharedMessage />

Si el componente SharedMessage se coloca en un componente que define el modo de representación, hereda el modo de representación aplicado.

En el ejemplo siguiente, el componente SharedMessage es interactivo a través de una conexión SignalR al cliente. El botón llama a UpdateMessage y el mensaje se actualiza.

RenderMode6.razor:

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

<SharedMessage />

Componentes secundarios con diferentes modos de representación

En el ejemplo siguiente, ambos componentes SharedMessage se presentan previamente y aparecen cuando la página se muestra en el explorador.

  • El primer componente SharedMessage con la representación interactiva del lado servidor (SSR interactiva) es interactivo después de establecer el circuito SignalR.
  • El segundo componente SharedMessage con la representación del lado cliente (CSR) es interactivo después de que el lote de aplicaciones Blazor se haya descargado y el runtime de .NET esté activo en el cliente.

RenderMode7.razor:

@page "/render-mode-7"

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

Componente secundario con un parámetro serializable

En el ejemplo siguiente se muestra un componente secundario interactivo que toma un parámetro. Los parámetros deben ser serializables.

RenderMode8.razor:

@page "/render-mode-8"

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

No se admiten los parámetros de componentes no serializables, como el contenido secundario o un fragmento de representación. En el ejemplo siguiente, pasar contenido secundario al componente SharedMessage produce un error de runtime.

RenderMode9.razor:

@page "/render-mode-9"

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

Error:

System.InvalidOperationException: no se puede pasar el parámetro "ChildContent" al componente "SharedMessage" con el modo de representación "InteractiveServerRenderMode". Esto se debe a que el parámetro es del tipo delegado "Microsoft.AspNetCore.Components.RenderFragment", que es código arbitrario y no se puede serializar.

Para eludir la limitación anterior, encapsula el componente secundario en otro componente que no tenga el parámetro. Este es el enfoque adoptado en la plantilla de proyecto de Blazor Web App con el componente Routes (Components/Routes.razor) para encapsular el componente Router.

WrapperComponent.razor:

<SharedMessage>
    Child content
</SharedMessage>

RenderMode10.razor:

@page "/render-mode-10"

<WrapperComponent @rendermode="InteractiveServer" />

En el ejemplo anterior:

  • El contenido secundario se pasa al componente SharedMessage sin generar un error de runtime.
  • El componente SharedMessage se representa de forma interactiva en el servidor.

Componente secundario con un modo de representación diferente al primario

No intentes aplicar a un componente secundario un modo de representación interactivo distinto del modo de representación de su elemento primario.

El siguiente componente produce un error de runtime cuando se representa el componente:

RenderMode11.razor:

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

<SharedMessage @rendermode="InteractiveWebAssembly" />

Error:

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 de SSR estática en una aplicación interactiva globalmente

Hay casos en los que la especificación de la aplicación llama a los componentes para adoptar la representación estática del lado servidor (SSR estática) y solo se ejecuta en el servidor, mientras que rest de la aplicación usará un modo de representación interactiva.

Este enfoque solo es útil cuando la aplicación tiene páginas específicas que no pueden trabajar con la representación interactiva de Servidor o WebAssembly. Por ejemplo, adopta este enfoque para las páginas que dependen de la lectura y escritura de cookies de HTTP y solo pueden funcionar en un ciclo de solicitud/respuesta en lugar de la representación interactiva. En el caso de las páginas que funcionan con la representación interactiva, no debes obligarlas a usar la representación SSR estática, ya que es menos eficaz y tiene menos capacidad de respuesta para el usuario final.

Marca cualquier página de componentes Razor con el atributo [ExcludeFromInteractiveRouting] asignado con la directiva Razor@attribute:

@attribute [ExcludeFromInteractiveRouting]

La aplicación del atributo hace que la navegación a la página salga del enrutamiento interactivo. La navegación entrante se ve forzada a realizar una recarga de página completa en su lugar resolviendo la página a través del enrutamiento interactivo. La recarga de página completa obliga al componente raíz de nivel superior, normalmente el componente App (App.razor), a volver a representar desde el servidor, lo que permite que la aplicación cambie a otro modo de representación de nivel superior.

El método de extensión HttpContext.AcceptsInteractiveRouting permite al componente detectar si [ExcludeFromInteractiveRouting] se aplica a la página actual.

En el componente App, usa el patrón en el ejemplo siguiente:

  • Páginas que no están anotadas con el valor predeterminado [ExcludeFromInteractiveRouting] para el modo de representación InteractiveServer con interactividad global. Puedes reemplazar InteractiveServer por InteractiveWebAssembly o InteractiveAuto para especificar otro modo de representación global predeterminado.
  • Páginas anotadas con la adopción de SSR estática [ExcludeFromInteractiveRouting] (a PageRenderMode se le asigna null).
<!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;
}

Una alternativa al uso del método de extensión HttpContext.AcceptsInteractiveRouting es leer manualmente los metadatos del punto de conexión mediante HttpContext.GetEndpoint()?.Metadata.

Hay dos enfoques que se pueden adoptar para controlar detalladamente los modos de representación, cada uno de los cuales se describe en las siguientes subsecciones:

  • Área (carpeta) de componentes de SSR estática: tiene un área (carpeta) de la aplicación con componentes que deben adoptar la SSR estática y compartir el mismo prefijo de ruta de acceso. La aplicación controla el modo de representación globalmente estableciendo el modo de representación del componente Routes en el componente App en función de la ruta de acceso a la carpeta.

  • Componentes de SSR estática distribuidos por la aplicación: tiene componentes repartidos por la aplicación en varias ubicaciones que deben adoptar la SSR estática y que solo se ejecutan en el servidor. Los componentes que solo son de SSR estática no están en una sola carpeta y no comparten un prefijo de ruta de acceso común. La aplicación controla el modo de representación por componente estableciendo el modo de representación con la directiva @rendermode en instancias de componentes. Se usa la reflexión del componente App para establecer el modo de representación en el componente Routes.

En ambos casos, el componente que deba adoptar la SSR estática también deberá forzar una recarga de página completa.

En los ejemplos siguientes, se usa el parámetro en cascada HttpContext para determinar si la página se representa estáticamente. Un HttpContext null indica que el componente se representa de forma interactiva, lo que resulta útil como señal en el código de la aplicación para desencadenar una recarga de página completa.

Área (carpeta) de componentes de SSR estática

La plantilla de proyecto de Blazor Web App usa el enfoque descrito en esta subsección con autenticación individual e interactividad global.

Un área (carpeta) de la aplicación contiene los componentes que debe adoptar la SSR estática y que solo se ejecutan en el servidor. Los componentes de la carpeta comparten el mismo prefijo de ruta de acceso. Por ejemplo, los componentes IdentityRazor de la plantilla de proyecto de Blazor Web App están en la carpeta Components/Account/Pages y comparten el prefijo de ruta de acceso raíz /Account.

La carpeta también contiene un archivo _Imports.razor, que aplica un diseño de cuenta personalizado a los componentes de la carpeta:

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

La carpeta Shared mantiene el componente de diseño AccountLayout. El componente usa HttpContext para determinar si el componente ha adoptado SSR estática. Los componentes Identity deben representarse en el servidor con la SSR estática porque establecen cookies Identity. Si el valor de HttpContext es null, el componente se representa de forma interactiva y se realiza una recarga de página completa llamando a NavigationManager.Refresh con forceLoad establecido en true. Esto fuerza una representación completa de la página mediante la SSR estática.

Components/Account/Shared/AccountLayout.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:

En la plantilla de proyecto de Blazor Web App, hay un segundo archivo de diseño (ManageLayout.razor en la carpeta Components/Account/Shared) para los componentes Identity de la carpeta Components/Account/Pages/Manage. La carpeta Manage tiene su propio archivo _Imports.razor para aplicar al ManageLayout para los componentes de la carpeta. En sus propias aplicaciones, el uso de archivos _Imports.razor anidados es un enfoque útil para aplicar diseños personalizados a grupos de páginas.

En el componente App, cualquier solicitud de un componente de la carpeta Account aplica un modo de representación null que aplica la SSR estática. Otras solicitudes de componentes reciben una aplicación global del modo de representación de SSR interactiva (InteractiveServer).

Importante

La aplicación de un modo de representación null no siempre aplica la SSR estática. Simplemente, ocurre que se comporta de esa manera con el enfoque que se muestra en esta sección.

Un modo de representación null resulta prácticamente lo mismo que no especificar un modo de representación, lo que da como resultado que el componente herede el modo de representación de su elemento primario. En este caso, el componente App se representará mediante la SSR estática, por lo que un modo de representación null dará como resultado el componente Routes heredando la SSR estática del componente App. Si se especificase un modo de representación null para un componente secundario cuyo elemento primario usase un modo de representación interactiva, el elemento secundario heredará el mismo modo de representación interactiva.

Components/App.razor:

<Routes @rendermode="RenderModeForPage" />

...

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

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

En el código anterior, cambia el marcador de posición {INTERACTIVE RENDER MODE} por el valor adecuado, en función de si el rest de la aplicación debiera adoptar la representación global InteractiveServer, InteractiveWebAssembly o InteractiveAuto.

Los componentes que deben adoptar SSR estáticas en la carpeta Account no son necesarios para establecer el diseño, que se aplica a través del archivo _Imports.razor. Los componentes no establecen un modo de representación porque deben representarse con una SSR estática. No se debe hacer nada más para que los componentes de la carpeta Account apliquen la SSR estática.

Componentes de SSR estática distribuidos por la aplicación

En la subsección anterior, la aplicación controla el modo de representación de los componentes estableciendo el modo de representación globalmente en el componente App. Como alternativa, el componente App también puede adoptar modos de representación por componente para establecer el modo de representación, lo que permite que los componentes se extiendan por la aplicación para aplicar la adopción de la SSR estática. En esta subsección se describe el enfoque.

La aplicación tiene un diseño personalizado que se puede aplicar a los componentes de la aplicación. Normalmente, un componente compartido para la aplicación se coloca en la carpeta Components/Layout. El componente usa HttpContext para determinar si el componente ha adoptado SSR estática. Si el valor de HttpContext es null, el componente se representa de forma interactiva y se realiza una recarga de página completa llamando a NavigationManager.Refresh con forceLoad establecido en true. Esto desencadena una solicitud al servidor para el componente.

Components/Layout/StaticSsrLayout.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);
        }
    }
}

En el componente App, la reflexión se usa para establecer el modo de representación. El modo de representación que se asigne al archivo de definición del componente individual se aplicará al componente Routes.

Components/App.razor:

<Routes @rendermode="RenderModeForPage" />

...

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

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

Cada componente que deba adoptar la SSR estática establecerá el diseño personalizado y no especificará un modo de representación. Si no se especificase un modo de representación, se obtendrá un valor de null de RenderModeAttribute.Mode en el componente App, lo que no dará como resultado ningún modo de representación asignado a la instancia de componente Routes y a la aplicación de la SSR estática.

Importante

La aplicación de un modo de representación null no siempre aplica la SSR estática. Simplemente, ocurre que se comporta de esa manera con el enfoque que se muestra en esta sección.

Un modo de representación null resulta prácticamente lo mismo que no especificar un modo de representación, lo que da como resultado que el componente herede el modo de representación de su elemento primario. En este caso, el componente App se representará mediante la SSR estática, por lo que un modo de representación null dará como resultado el componente Routes heredando la SSR estática del componente App. Si se especificase un modo de representación null para un componente secundario cuyo elemento primario usase un modo de representación interactiva, el elemento secundario heredará el mismo modo de representación interactiva.

No se debe hacer nada más para que los componentes apliquen la SSR estática que aplicar el diseño personalizado sin establecer un modo de representación interactiva:

@layout BlazorSample.Components.Layout.StaticSsrLayout

Los componentes interactivos de la aplicación evitan aplicar el diseño personalizado de SSR estática y solo establecen un modo de representación interactiva adecuado, que tras la reflexión del componente App se aplica al componente Routes:

@rendermode {INTERACTIVE RENDER MODE}

En el código anterior, cambia el marcador de posición {INTERACTIVE RENDER MODE} por el valor adecuado, en función de si el componente debiera adoptar la representación InteractiveServer, InteractiveWebAssembly o InteractiveAuto.

Los servicios del lado cliente no se resuelven durante la representación previa

Suponiendo que la representación previa no está deshabilitada para un componente o para la aplicación, un componente del proyecto .Client se representa previamente en el servidor. Dado que el servidor no tiene acceso a los servicios Blazor registrados del lado cliente, no es posible insertar estos servicios en un componente sin recibir un error que indica que el servicio no se puede encontrar durante la representación previa.

Por ejemplo, considera el siguiente componente Home en el proyecto .Client de una Blazor Web App con la representación automática interactiva o la representación interactiva de WebAssembly global. El componente intenta insertar IWebAssemblyHostEnvironment para obtener el nombre del entorno.

@page "/"
@inject IWebAssemblyHostEnvironment Environment

<PageTitle>Home</PageTitle>

<h1>Home</h1>

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

No se produce ningún error en tiempo de compilación, pero se produce un error en tiempo de ejecución durante la representación previa:

No se puede proporcionar un valor para la propiedad "Environment" en el tipo "BlazorSample.Client.Pages.Home". No hay ningún servicio registrado de tipo "Microsoft.AspNetCore.Components.WebAssembly.Hosting.IWebAssemblyHostEnvironment".

Este error se produce porque el componente debe compilarse y ejecutarse en el servidor durante la representación previa, pero IWebAssemblyHostEnvironment no es un servicio registrado en el servidor.

Si la aplicación no requiere el valor durante la representación previa, este problema se puede resolver insertando IServiceProvider para obtener el servicio en lugar del propio tipo de servicio:

@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;
        }
    }
}

Sin embargo, el enfoque anterior no es útil si la lógica requiere un valor durante la representación previa.

También puedes evitar el problema si deshabilita la representación previa del componente, pero es una medida extrema que se debe tomar en muchos casos que no cumplan las especificaciones del componente.

Hay tres enfoques que puede adoptar para abordar este escenario. Se presentan a continuación, del más al menos recomendado:

  • Recomendado para servicios de marco compartidos: para los servicios de marco compartidos que simplemente no están registrados en el lado del servidor en el proyecto principal, registra los servicios en el proyecto principal, lo que hace que estén disponibles durante la representación previa. Para obtener un ejemplo de este escenario, consulta las instrucciones para los servicios de HttpClient en Llamada a una API web desde una aplicación de ASP.NET Core Blazor.

  • Recomendado para servicios fuera del marco compartido: crea una implementación de servicio personalizada para el servicio en el servidor. Normalmente, usa el servicio en componentes interactivos del proyecto .Client. Para obtener una demostración de este enfoque, consulta los entornosBlazor de ASP.NET Core.

  • Crea una abstracción de servicio y crea implementaciones para el servicio en los proyectos de servidor y .Client. Registra los servicios en cada proyecto. Inserta el servicio personalizado en el componente.

  • Es posible que puedas agregar una referencia de paquete de proyecto .Client a un paquete del lado servidor y revertir al uso de la API del lado servidor al realizar la representación previa en el servidor.

Detección de componentes de ensamblados adicionales

Los ensamblados adicionales deben revelarse al marco de Blazor para detectar componentes de Razor enrutables en proyectos a los que se hace referencia. Para obtener más información, consulta Enrutamiento y navegación de Blazor de ASP.NET Core.

Cierre de circuitos cuando no haya componentes del servidor interactivo restantes

Los componentes del Servidor interactivo controlan los eventos de la interfaz de usuario web mediante una conexión en tiempo real con el explorador denominado circuito. Un circuito y su estado asociado se crean cuando se representa un componente de Servidor interactivo raíz. El circuito se cierra cuando no quedan componentes de Servidor interactivo en la página, lo que libera los recursos del servidor.

Modos de representación abreviados personalizados

La directiva @rendermode toma un único parámetro que es una instancia estática de tipo IComponentRenderMode. El atributo de directiva @rendermode puede tomar cualquier instancia del modo de representación, estática o no. El marco de Blazor proporciona la clase estática RenderMode con algunos modos de representación predefinidos para mayor comodidad, pero puede crear los suyos propios.

Normalmente, un componente usa la siguiente directiva @rendermode para deshabilitar la representación previa:

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

Sin embargo, considera el ejemplo siguiente que crea un modo de representación interactivo del lado servidor abreviado sin representación previa mediante el archivo _Imports de la aplicación (Components/_Imports.razor):

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

Usa el modo de representación abreviado en componentes en toda la carpeta Components:

@rendermode InteractiveServerWithoutPrerendering

Como alternativa, una única instancia de componente puede definir un modo de representación personalizado mediante un campo privado:

@rendermode interactiveServerWithoutPrerendering

...

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

Por el momento, el enfoque del modo de representación abreviado probablemente solo sea útil para reducir el nivel de detalle de especificar la marca prerender. El enfoque abreviado podría ser más útil en el futuro si se dispone de marcas adicionales para la representación interactiva y se desea crear modos de representación abreviados con diferentes combinaciones de marcas.

Inserción de servicios a través de un archivo de importación de nivel superior (_Imports.razor)

Esta sección solo se aplica a Blazor Web App.

Un archivo de importación de nivel superior en la carpeta Components (Components/_Imports.razor) inserta sus referencias en todos los componentes de la jerarquía de carpetas, que incluye el componente App (App.razor). El componente App siempre se representa estáticamente incluso si la representación previa de un componente de página está deshabilitado. Por lo tanto, la inserción de servicios a través del archivo de importación de nivel superior da como resultado la resolución de dos instancias del servicio en los componentes de página.

Para solucionar este escenario, inserta el servicio en un nuevo archivo de importaciones colocado en la carpeta Pages (Components/Pages/_Imports.razor). Desde esa ubicación, el servicio solo se resuelve una vez en los componentes de la página.

Recursos adicionales