blazor-hola-mundo-estructura

Hola Mundo en Blazor: flujo de ejecución de la plantilla

  • 5 min

Un «Hola Mundo» en Blazor es el ejemplo mínimo con el que comprobamos el recorrido completo de una página, desde la petición hasta el HTML que aparece en el navegador.

En el artículo anterior dejamos el entorno listo y la solución creada. Ahora vamos a pulsar Ejecutar (o F5) y, sobre todo, a entender por qué funciona.

Vamos a recorrer la plantilla moderna de Blazor desde que el navegador hace la petición hasta que vemos el texto en pantalla.

El objetivo: Home.razor

Cuando abres el navegador en https://localhost:xxxx/, lo que estás viendo es el renderizado del componente Home.razor.

Lo encontrarás en la carpeta Components/Pages/Home.razor.

@page "/"

<PageTitle>Home</PageTitle>

<h1>Hello, world!</h1>

Welcome to your new app.
Copied!

Es un archivo muy simple, pero tiene detalles cruciales:

  1. Directiva @page "/": Esto es lo que define la ruta. Le dice a Blazor: “Cuando el usuario pida la raíz del sitio, cárgame a mí”.
  2. HTML estándar: El resto (h1, texto) es HTML normal.
  3. Componentes integrados: <PageTitle> es un componente de Blazor que nos permite modificar el título de la pestaña del navegador dinámicamente.

Entonces, ¿cómo sabe Blazor que debe mostrar este archivo? Para responder tenemos que ir al principio de todo.

El punto de entrada: Program.cs

Como cualquier aplicación de consola en .NET (sí, ASP.NET Core es una app de consola vitaminada), todo empieza en el Program.cs.

Aquí se configura el servidor web y los servicios. Vamos a ver las líneas clave para Blazor:

var builder = WebApplication.CreateBuilder(args);

// 1. REGISTRO DE SERVICIOS
// Agrega los servicios necesarios para renderizar componentes Razor
builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents()  // Habilita el modo Server (SignalR)
    .AddInteractiveWebAssemblyComponents(); // Habilita el modo WebAssembly

var app = builder.Build();

// ... configuración de HTTPS y ficheros estáticos ...

app.UseAntiforgery(); // Seguridad contra CSRF

// 2. MAPEO DE COMPONENTES
// Aquí decimos: "El componente raíz de toda la app es 'App'"
app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode()
    .AddInteractiveWebAssemblyRenderMode()
    .AddAdditionalAssemblies(typeof(Counter).Assembly); // Conecta con el proyecto Client

app.Run();
Copied!

Fíjate en app.MapRazorComponents<App>(). Esta línea es la que conecta la petición HTTP con el sistema de componentes de Blazor, designando a App.razor como el padre de todos los componentes.

El documento HTML: App.razor

El archivo Components/App.razor define la estructura HTML base del documento y aloja el componente de rutas.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <base href="/" />
    <link rel="stylesheet" href="bootstrap/bootstrap.min.css" />
    <link rel="stylesheet" href="app.css" />
    <link rel="stylesheet" href="BlazorApp1.styles.css" />
    <HeadOutlet />
</head>

<body>
    <Routes />
    <script src="_framework/blazor.web.js"></script>
</body>

</html>
Copied!

Aquí hay tres elementos importantes:

  1. <base href="/" />: Imprescindible. Le dice al navegador cómo resolver las rutas relativas. Sin esto, la navegación de Blazor no funciona.
  2. <Routes />: Blazor inyecta en este punto el contenido dinámico. Es un placeholder que indica dónde va la página solicitada por el usuario.
  3. blazor.web.js: Es el script que arranca el framework en el navegador. Se encarga de conectar con el servidor (si es Server) o cargar el runtime (si es WASM).

¿Ves el archivo BlazorApp1.styles.css? Es un archivo virtual que genera Blazor automáticamente para el CSS Isolation (los estilos encapsulados de cada componente).

El enrutador: Routes.razor

El componente <Routes /> que vimos arriba está definido en Routes.razor. Es el cerebro de la navegación.

<Router AppAssembly="@typeof(Program).Assembly">
    <Found Context="routeData">
        <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
        <FocusOnNavigate RouteData="@routeData" Selector="h1" />
    </Found>
    <NotFound>
        <PageTitle>Not found</PageTitle>
        <LayoutView Layout="@typeof(MainLayout)">
            <p role="alert">Sorry, there's nothing at this address.</p>
        </LayoutView>
    </NotFound>
</Router>
Copied!

Su lógica es sencilla:

  1. Escanea todos los componentes del ensamblado (AppAssembly).
  2. Busca aquellos que tengan la directiva @page.
  3. Compara la URL del navegador con la ruta del componente.
  4. Si encuentra coincidencia (Found): Renderiza el componente usando el DefaultLayout (que es MainLayout).
  5. Si NO encuentra coincidencia (NotFound): Muestra el mensaje de error 404.

La plantilla común: MainLayout.razor

Finalmente, antes de pintar Home.razor, Blazor lo envuelve en el MainLayout.razor. Este componente define la estructura común de la web (la barra lateral, el menú superior, el pie de página).

@inherits LayoutComponentBase

<div class="page">
    <div class="sidebar">
        <NavMenu />
    </div>

    <main>
        <div class="top-row px-4">
            <a href="https://learn.microsoft.com/aspnet/core/" target="_blank">About</a>
        </div>

        <article class="content px-4">
            @Body
        </article>
    </main>
</div>
Copied!

El punto clave aquí es @Body. En esa posición exacta es donde se renderizará nuestro Home.razor.

Flujo de ejecución

Para que nos quede el mapa mental claro, esto es lo que ocurre cuando pulsas Enter en la barra de direcciones:

Petición: El navegador solicita https://tudominio/.

Server (Program.cs): ASP.NET Core recibe la petición y la pasa al middleware de Blazor.

Root (App.razor): Se empieza a generar el HTML. Se encuentra el componente <Routes />.

Router: El Router ve que la URL es / y busca un componente con @page "/". Encuentra Home.razor.

Layout: El Router ve que debe usar MainLayout. Instancia el Layout.

Renderizado: Dentro del @Body del Layout, se instancia Home.razor.

Respuesta: El servidor devuelve el HTML completo al navegador (SSR).

Interactividad: Si la página usa un modo interactivo, blazor.web.js inicia el runtime correspondiente y conecta los controladores de eventos. En SSR estático, la página permanece sin interactividad de Blazor.