.NET 9 Blazor: Desarrollo Full-Stack con Blazor United en 2026
.NET 9 Blazor United combina renderizado estático SSR, Server y WebAssembly en un framework full-stack unificado. Tutorial práctico que cubre modos de renderizado, streaming, inyección por constructor y patrones listos para producción.

Blazor United en .NET 9 fusiona tres estrategias de renderizado — renderizado estático del lado del servidor (SSR), Server interactivo y WebAssembly — en un solo framework full-stack cohesivo. Este modelo unificado, introducido en .NET 8 y perfeccionado en .NET 9, elimina la necesidad de elegir entre diferentes modelos de hospedaje de Blazor antes de escribir una sola línea de código.
Blazor United permite combinar SSR estático, interactividad Server e interactividad WebAssembly dentro de la misma aplicación. Cada componente declara de forma independiente su modo de renderizado, lo que brinda un control granular sobre el rendimiento y la interactividad por página.
Configuración de una aplicación Blazor Web con .NET 9
La plantilla blazorweb de .NET 9 genera un proyecto preconfigurado para los tres modos de renderizado. La configuración requiere el SDK de .NET 9 (versión 9.0.100 o posterior) y crea tanto el proyecto del servidor como el del cliente (WASM) en un solo comando.
# Crear una nueva Blazor Web App con todos los modos de renderizado habilitados
dotnet new blazorweb -n FullStackApp --interactivity Auto --all-interactive false
cd FullStackApp
dotnet runEl flag --interactivity Auto habilita los modos de renderizado Server y WebAssembly. El parámetro --all-interactive false mantiene el SSR estático como modo predeterminado, de modo que la interactividad se activa componente por componente en lugar de globalmente.
Los modos de renderizado de Blazor en .NET 9
Cada componente en una Blazor Web App adopta un modo de renderizado que determina dónde se ejecuta, si soporta interactividad y cómo se comunica con el servidor. .NET 9 ofrece cuatro modos distintos.
| Modo de renderizado | Hospedaje | Interactividad | Ideal para | |---|---|---|---| | SSR estático | Servidor | Ninguna | Páginas de marketing, documentación, contenido SEO | | Interactive Server | Servidor vía SignalR | Completa | Dashboards, CRUD, formularios | | Interactive WebAssembly | Navegador vía WASM | Completa | Modo offline, lógica intensiva del lado del cliente | | Interactive Auto | Servidor luego WASM | Completa | Lo mejor de ambos — carga rápida + independencia |
El modo de renderizado se establece a nivel de componente con la directiva @rendermode. Esta granularidad por componente permite que una sola página combine secciones estáticas e interactivas.
@page "/dashboard"
@rendermode InteractiveServer
<PageTitle>Dashboard</PageTitle>
<h1>Real-Time Metrics</h1>
<!-- This component renders interactively via SignalR -->
<MetricsChart />
<!-- Static content below renders as plain HTML -->
<footer>Updated every 5 seconds</footer>Una adición a la API de .NET 9 — ComponentBase.RendererInfo — permite que los componentes detecten su modo de renderizado actual en tiempo de ejecución, habilitando lógica condicional basada en el contexto de ejecución.
@if (RendererInfo.IsInteractive)
{
<button @onclick="HandleClick">Interactive Action</button>
}
else
{
<a href="/fallback">Static Fallback Link</a>
}
@code {
private void HandleClick()
{
// Runs only in interactive modes (Server or WASM)
}
}Renderizado en streaming para páginas con carga asíncrona
Las páginas SSR estáticas que obtienen datos de forma asíncrona pueden bloquear la respuesta hasta que todas las tareas se completen. El renderizado en streaming resuelve este problema enviando HTML de marcador de posición inmediatamente, y luego transmitiendo el contenido final a medida que los datos llegan. En .NET 9, el atributo [StreamRendering] ya no requiere el parámetro true — se activa por defecto.
@page "/products"
@attribute [StreamRendering]
<PageTitle>Product Catalog</PageTitle>
@if (products is null)
{
<p>Loading products...</p>
}
else
{
<div class="product-grid">
@foreach (var product in products)
{
<ProductCard Item="@product" />
}
</div>
}
@code {
private List<Product>? products;
// Data loads asynchronously; streaming pushes updates to the browser
protected override async Task OnInitializedAsync()
{
products = await ProductService.GetAllAsync();
}
}El renderizado en streaming utiliza la codificación de transferencia por fragmentos de HTTP/1.1 (chunked transfer encoding), compatible con todos los navegadores modernos. El contenido de marcador de posición se muestra al instante, y el marcado final lo reemplaza sin recargar la página por completo.
Inyección por constructor en componentes Blazor
.NET 9 introduce la inyección por constructor para componentes Blazor, complementando la directiva @inject y el atributo [Inject] existentes. Combinada con los constructores primarios de C# 12, las dependencias de servicios se convierten en parte de la firma de tipo del componente.
@page "/orders"
@rendermode InteractiveServer
<h2>Order History</h2>
@if (orders is not null)
{
<table>
<thead>
<tr><th>Order ID</th><th>Date</th><th>Total</th></tr>
</thead>
<tbody>
@foreach (var order in orders)
{
<tr>
<td>@order.Id</td>
<td>@order.PlacedAt.ToShortDateString()</td>
<td>@order.Total.ToString("C")</td>
</tr>
}
</tbody>
</table>
}
@code {
// Constructor injection via primary constructor
[Inject] public required IOrderService OrderService { get; set; }
[Inject] public required NavigationManager Nav { get; set; }
private List<Order>? orders;
protected override async Task OnInitializedAsync()
{
orders = await OrderService.GetRecentOrdersAsync();
}
}La inyección por constructor hace las dependencias explícitas y simplifica las pruebas unitarias. Los servicios registrados en Program.cs se resuelven automáticamente, incluyendo los servicios con clave agregados mediante builder.Services.AddKeyedScoped<T>().
¿Listo para aprobar tus entrevistas de .NET?
Practica con nuestros simuladores interactivos, flashcards y tests técnicos.
Modo Interactive Auto — lo mejor de ambos mundos
El modo Auto ofrece el tiempo de carga percibido más rápido. En la primera visita, el componente se ejecuta en el servidor vía SignalR mientras el runtime de WebAssembly se descarga en segundo plano. En visitas posteriores, la ejecución se traslada completamente al navegador.
@page "/chat"
@rendermode InteractiveAuto
<h2>Live Chat</h2>
<div class="chat-messages">
@foreach (var msg in messages)
{
<div class="message">@msg.Author: @msg.Text</div>
}
</div>
<input @bind="newMessage" @onkeydown="HandleKey" placeholder="Type a message..." />
@code {
[Inject] public required IChatService ChatService { get; set; }
private List<ChatMessage> messages = new();
private string newMessage = string.Empty;
protected override async Task OnInitializedAsync()
{
messages = await ChatService.GetRecentMessagesAsync();
}
private async Task HandleKey(KeyboardEventArgs e)
{
if (e.Key == "Enter" && !string.IsNullOrWhiteSpace(newMessage))
{
await ChatService.SendAsync(newMessage);
newMessage = string.Empty;
}
}
}El modo Auto requiere que las dependencias y la lógica del componente funcionen tanto en el contexto del servidor como en WASM. Los servicios deben abstraerse detrás de interfaces y registrarse en los contenedores de inyección de dependencias tanto del servidor como del cliente.
Reconexión y resiliencia en .NET 9
.NET 9 reescribe la lógica de reconexión de Blazor Server con una estrategia de backoff exponencial. En lugar de reintentar a intervalos fijos, el framework comienza con reintentos rápidos y aumenta progresivamente el intervalo — reduciendo la carga del servidor durante las interrupciones mientras se recupera rápidamente de disrupciones breves.
Mejoras clave:
- Navegar de vuelta a una pestaña dispara un intento de reconexión inmediato
- Si el servidor ya liberó el circuito, la página se actualiza automáticamente
- La interfaz predeterminada muestra "Reconectando al servidor..." con un indicador de progreso
- Los intervalos de reintento son configurables vía
Blazor.start()
Blazor.start({
circuit: {
reconnectionOptions: {
retryIntervalMilliseconds: (retryNumber) => {
// Exponential backoff: 200ms, 400ms, 800ms, max 30s
return Math.min(200 * Math.pow(2, retryNumber), 30000);
},
maxRetries: 15
}
}
});SSR estático con interactividad selectiva
La arquitectura recomendada para la mayoría de las Blazor Web Apps en 2026 comienza con SSR estático como predeterminado, agregando interactividad solo donde es necesario. El atributo [ExcludeFromInteractiveRouting] (nuevo en .NET 9) marca las páginas que deben permanecer estáticas — útil para páginas que dependen de cookies HTTP o del ciclo de solicitud/respuesta.
@page "/privacy"
@attribute [ExcludeFromInteractiveRouting]
<PageTitle>Privacy Policy</PageTitle>
<!-- This page always renders as static HTML -->
<!-- Even if global interactivity is enabled -->
<article>
<h1>Privacy Policy</h1>
<p>Last updated: April 2026</p>
<!-- Content -->
</article>Este patrón funciona bien con MapStaticAssets, un nuevo middleware de .NET 9 que comprime y agrega fingerprints a los archivos estáticos en tiempo de compilación, reemplazando el enfoque anterior de UseStaticFiles con una entrega optimizada lista para usar.
Ganancias de rendimiento con la compilación AOT de .NET 9
La compilación AOT (Ahead-of-Time) de .NET 9 reduce el tamaño de los payloads de WebAssembly hasta en un 40% en comparación con .NET 8. El arranque de Blazor WASM es un 25% más rápido según los benchmarks de Google Lighthouse. Estas mejoras se aplican automáticamente al publicar con AOT habilitado.
# Publish with AOT for production
dotnet publish -c Release -p:RunAOTCompilation=trueLa compresión de WebSocket también está habilitada por defecto para los componentes interactivos Server. Una Content Security Policy (frame-ancestors: 'self') se aplica automáticamente para mitigar los vectores de ataque relacionados con la compresión.
¡Empieza a practicar!
Pon a prueba tu conocimiento con nuestros simuladores de entrevista y tests técnicos.
Conclusión
- Blazor United en .NET 9 elimina la decisión del modelo de hospedaje al combinar SSR estático, Server y WebAssembly en un solo proyecto
- Los modos de renderizado se configuran por componente con
@rendermodepara optimizar cada página de forma independiente — estático para SEO, Server para dashboards, Auto para escenarios híbridos - El renderizado en streaming con
[StreamRendering]elimina los retrasos de carga en páginas con mucha actividad asíncrona - La inyección por constructor (nueva en .NET 9) hace que las dependencias de los componentes sean explícitas y testeables
- El modo Auto ofrece un primer renderizado rápido vía Server, luego cambia a WASM para total independencia del cliente
- El backoff exponencial en la reconexión reduce las conexiones perdidas y elimina las recargas manuales de página
- La compilación AOT reduce el tamaño de los payloads WASM en un 40% y el tiempo de arranque en un 25%
- Toda Blazor Web App debería comenzar con SSR estático por defecto y agregar interactividad solo donde la experiencia de usuario lo exija
¡Empieza a practicar!
Pon a prueba tu conocimiento con nuestros simuladores de entrevista y tests técnicos.
Etiquetas
Compartir
Artículos relacionados

Entity Framework Core: Optimización del Rendimiento y Buenas Prácticas en 2026
Guía completa de optimización de rendimiento con Entity Framework Core 10 en .NET 10. AsNoTracking, consultas compiladas, actualizaciones por lotes, split queries y LeftJoin.

Clean Architecture con .NET: Guía Práctica
Domina Clean Architecture en .NET con C#. Aprende los principios SOLID, la separación de capas y los patrones de implementación para aplicaciones mantenibles.

Preguntas de Entrevista C# y .NET: Guía Completa 2026
Las 17 preguntas más frecuentes en entrevistas de C# y .NET. LINQ, async/await, inyección de dependencias, Entity Framework y buenas prácticas con respuestas detalladas.