Compartir a través de


Estructura de proyecto de aplicaciones Blazor

Sugerencia

Este contenido es un extracto del libro electrónico "Blazor for ASP.NET Web Forms Developers for Azure" (Blazor para desarrolladores de ASP.NET Web Forms), disponible en Documentación de .NET o como un PDF descargable y gratuito que se puede leer sin conexión.

Miniatura de portada del libro electrónico Blazor para desarrolladores de ASP.NET Web Forms.

A pesar de las diferencias importantes en las estructuras de proyecto, ASP.NET Web Forms y Blazor comparten muchos conceptos similares. Aquí veremos la estructura de un proyecto Blazor y lo comparamos con otro de ASP.NET Web Forms.

Para crear su primera aplicación de Blazor, siga las instrucciones que se indican en los pasos de introducción deBlazor. Puede seguir las instrucciones para crear una aplicación Blazor Server o una BlazorWebAssembly hospedada en ASP.NET Core. A excepción de la lógica específica del modelo de hospedaje, la mayor parte del código en ambos proyectos es el mismo.

Archivo del proyecto

Las aplicaciones Blazor Server son proyectos de .NET. El archivo del proyecto para la aplicación Blazor Server es muy sencilla:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
  </PropertyGroup>

</Project>

El archivo del proyecto de una aplicación BlazorWebAssembly tiene un aspecto ligeramente más complicado (los números de versión exactos pueden variar):

<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">

  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.0" />
    <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.0" PrivateAssets="all" />
  </ItemGroup>

</Project>

BlazorWebAssemblyEl proyecto tiene como destino Microsoft.NET.Sdk.BlazorWebAssembly, en lugar del SDK de Microsoft.NET.Sdk.Web, porque se ejecutan en el explorador, en un entorno de ejecución .NET basado en WebAssembly. No se puede instalar .NET en un explorador web, tal como se podría hacer en un servidor o una máquina del desarrollador. Por consiguiente, el proyecto hace referencia al marco Blazor mediante referencias de paquete individuales.

En cambio, un proyecto de ASP.NET Web Forms predeterminado incluye casi 300 líneas de XML en su archivo .csproj, la mayoría de las cuales están enumerando explícitamente los distintos archivos de código y contenido en el proyecto. Desde la publicación de .NET 5, las aplicaciones de Blazor Server y BlazorWebAssembly pueden compartir fácilmente un entorno de ejecución unificado.

Aunque están admitidas, las referencias de ensamblado individuales son menos comunes en los proyectos de .NET. La mayoría de las dependencias del proyecto se controlan como referencias de paquetes NuGet. Solo es necesario hacer referencia a las dependencias de paquetes de nivel superior en los proyectos de .NET. Las dependencias transitivas se incluyen automáticamente. En lugar de usar el archivo packages.config, que se encuentra normalmente en los proyectos de ASP.NET Web Forms para hacer referencia a los paquetes, las referencias de paquete se agregan al archivo del proyecto mediante el elemento <PackageReference>.

<ItemGroup>
  <PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
</ItemGroup>

Punto de entrada

El punto de entrada de la aplicación Blazor Server se define en el archivo Program.cs, tal como se verá en una aplicación de la consola. Cuando se ejecuta la aplicación, crea y ejecuta una instancia de host web con los valores predeterminados específicos de las aplicaciones web. El host web administra el ciclo de vida de la aplicación Blazor Server y configura los servicios de nivel de host. Algunos ejemplos de estos servicios son la configuración, el registro, la inserción de dependencias y el servidor HTTP. Este código es principalmente reutilizable y a menudo se deja sin cambios.

using BlazorApp3.Areas.Identity;
using BlazorApp3.Data;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddScoped<AuthenticationStateProvider, RevalidatingIdentityAuthenticationStateProvider<IdentityUser>>();
builder.Services.AddSingleton<WeatherForecastService>();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapControllers();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

app.Run();

BlazorWebAssembly Las aplicaciones también definen un punto de entrada en Program.cs. El código tiene un aspecto ligeramente distinto. El código es similar en que está configurando el host de la aplicación para proporcionar los mismos servicios de nivel de host a la aplicación. Sin embargo, el host de la aplicación WebAssembly no configura un servidor HTTP porque se ejecuta directamente en el explorador.

Las aplicaciones Blazor no usan un archivo Global.asax para definir la lógica de inicio de la aplicación. En su lugar, esta lógica se incluye en Program.cs o en una clase Startup relacionada a la que se hace referencia desde Program.cs. En cualquier caso, este código se usa para configurar la aplicación y los servicios específicos de la aplicación.

En una aplicación Blazor Server, el archivo Program.cs mostrado se usa para configurar el punto de conexión para la conexión en tiempo real que utiliza Blazor entre los exploradores y el servidor del cliente.

En una aplicación BlazorWebAssembly, el archivo Program.cs define los componentes raíz de la aplicación y dónde se deben representar:

using BlazorApp1;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;

var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");

builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });

await builder.Build().RunAsync();

Archivos estáticos

A diferencia de los proyectos de ASP.NET Web Forms, no todos los archivos de un proyecto de Blazor se pueden solicitar como archivos estáticos. Solo los archivos de la carpeta wwwroot son direccionables por web. Esta carpeta se conoce como "raíz web" de la aplicación. Todo lo demás que esté fuera de la raíz web de la aplicación no es direccionable por web. Esta configuración proporciona un nivel de seguridad adicional que evita la exposición accidental de archivos del proyecto a través de la web.

Configuración

Por lo general, la configuración de las aplicaciones de ASP.NET Web Forms se controla mediante uno o varios archivos web.config. Normalmente, las aplicaciones Blazor no tienen archivos web.config. Si lo hacen, el archivo solo se utiliza para configurar los valores específicos de IIS cuando se hospedan en este software. En su lugar, las aplicaciones Blazor Server usan las abstracciones de configuración de ASP.NET Core (actualmente, las aplicaciones BlazorWebAssembly no admiten las mismas abstracciones de configuración, pero es posible que dicha característica se agregue en el futuro). Por ejemplo, la aplicación Blazor Server predeterminada almacena algunos valores en appsettings.json.

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

En la sección Configuración, encontrará más información sobre la configuración en proyectos de ASP.NET Core.

Componentes de Razor

La mayoría de los archivos de los proyectos de Blazor son archivos .razor. Razor es un lenguaje de plantillas basado en HTML y C# que se usa para generar dinámicamente la interfaz de usuario web. Los archivos .razor definen los componentes que componen la interfaz de usuario de la aplicación. En su mayor parte, los componentes son idénticos tanto para las aplicaciones Blazor Server como para las aplicaciones BlazorWebAssembly. Los componentes de Blazor son análogos a los controles de usuario de ASP.NET Web Forms.

Cada archivo de componente de Razor se compila en una clase .NET cuando se compila el proyecto. La clase generada captura el estado del componente, la lógica de representación, los métodos de ciclo de vida, los controladores de eventos y otra lógica. En la sección Creación de componentes de interfaz de usuario reutilizables con Blazor, obtendrá más información sobre los componentes de creación.

Los archivos _Imports.razor no son archivos de componentes de Razor. En su lugar, definen un conjunto de directivas de Razor que se van a importar en otros archivos .razor, dentro de la misma carpeta y en sus subcarpetas. Por ejemplo, un archivo _Imports.razor es una manera convencional de agregar directivas using para los espacios de nombres usados habitualmente:

@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.AspNetCore.Components.WebAssembly.Http
@using Microsoft.JSInterop
@using BlazorApp1
@using BlazorApp1.Shared

Páginas

¿Dónde están las páginas de las aplicaciones Blazor? Blazor no define una extensión de archivo independiente para las páginas direccionables, como los archivos .aspx de las aplicaciones de ASP.NET Web Forms. En su lugar, las páginas se definen mediante la asignación de rutas a los componentes. Normalmente, una ruta se asigna mediante la directiva de Razor @page. Por ejemplo, el componente Counter creado en el archivo Pages/Counter.razor define la ruta siguiente:

@page "/counter"

El enrutamiento en Blazor se controla en el lado cliente, no en el servidor. A medida que el usuario navega en el explorador, Blazor intercepta la navegación y, después, representa el componente con la ruta coincidente.

Las rutas del componente no las infiere actualmente la ubicación del archivo del componente, tal como sucede con las páginas .aspx o Razor Pages en ASP.NET Core. Es posible que en el futuro se agregue esta característica. Cada ruta debe especificarse explícitamente en el componente. El almacenamiento de componentes enrutables en una carpeta Pages no tiene ningún significado especial y no es más que una convención.

En la sección Blazor encontrará más información sobre el enrutamiento en .

Layout

En las aplicaciones de ASP.NET Web Forms, un diseño de página común se controla mediante páginas maestras (Site.Master). En aplicaciones Blazor, el diseño de página se controla mediante componentes de diseño (Shared/MainLayout.razor). Los componentes de diseño se tratan con más detalle en la sección Páginas, enrutamiento y diseños.

Arranque de Blazor

Para arrancar Blazor, la aplicación debe realizar lo siguiente:

  • Especificar en qué lugar de la página se debe representar el componente raíz (App.Razor).
  • Agregar el script de marco de Blazor correspondiente.

En la aplicación Blazor Server, la página host del componente raíz se define en el archivo _Host.cshtml. Este archivo define una página de Razor, no un componente. Razor Pages usa la sintaxis Razor para definir una página direccionable por el servidor, de forma muy parecida a una página .aspx.

@page "/"
@namespace BlazorApp3.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
    Layout = "_Layout";
}

<component type="typeof(App)" render-mode="ServerPrerendered" />

El atributo render-mode se utiliza para definir dónde se debe representar un componente de nivel de raíz. La opción RenderMode indica la manera en que se debe representar el componente. En la tabla siguiente se describen las opciones de RenderMode admitidas.

Opción Descripción
RenderMode.Server Representado de forma interactiva una vez que se establece una conexión con el explorador.
RenderMode.ServerPrerendered Representado previamente en primer lugar y, después, representado de forma interactiva.
RenderMode.Static Representado como contenido estático.

El archivo _Layout.cshtml incluye el código HTML predeterminado para la aplicación y sus componentes.

@using Microsoft.AspNetCore.Components.Web
@namespace BlazorApp3.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<!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="css/bootstrap/bootstrap.min.css" />
    <link href="css/site.css" rel="stylesheet" />
    <link href="BlazorApp3.styles.css" rel="stylesheet" />
    <component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
</head>
<body>
    @RenderBody()

    <div id="blazor-error-ui">
        <environment include="Staging,Production">
            An error has occurred. This application may no longer respond until reloaded.
        </environment>
        <environment include="Development">
            An unhandled exception has occurred. See browser dev tools for details.
        </environment>
        <a href="" class="reload">Reload</a>
        <a class="dismiss">🗙</a>
    </div>

    <script src="_framework/blazor.server.js"></script>
</body>
</html>

La referencia de script a _framework/blazor.server.js establece la conexión en tiempo real con el servidor y, a continuación, trata todas las interacciones del usuario y las actualizaciones de la interfaz de usuario.

En la aplicación BlazorWebAssembly, la página host es un archivo HTML estático sencillo que se encuentra en wwwroot/index.html. El elemento <div> con el identificador denominado app se utiliza para indicar dónde se debe representar el componente raíz.

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

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

<body>
    <div id="app">Loading...</div>

    <div id="blazor-error-ui">
        An unhandled error has occurred.
        <a href="" class="reload">Reload</a>
        <a class="dismiss">🗙</a>
    </div>
    <script src="_framework/blazor.webassembly.js"></script>
</body>

</html>

El componente raíz que se va a representar se especifica en el archivo de la aplicación Program.cs con la flexibilidad de registrar los servicios mediante la inserción de dependencias. Para obtener más información, vea Inserción de dependencias de Blazor de ASP.NET Core.

var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");

Resultado de la compilación

Cuando se compila un proyecto Blazor, todos los componentes de Razor y los archivos de código se compilan en un único ensamblado. A diferencia de los proyectos de ASP.NET Web Forms, Blazor no admite la compilación en tiempo de ejecución de la lógica de la interfaz de usuario.

Ejecución de la aplicación con Recarga activa

Para ejecutar la aplicación Blazor Server, presione F5 en Visual Studio para ejecutarla con el depurador asociado, o Ctrl + F5 para ejecutarla sin el depurador asociado.

Para ejecutar la aplicación BlazorWebAssembly, elija uno de los siguientes enfoques:

  • Ejecutar el proyecto de cliente directamente con el servidor de desarrollo.
  • Ejecutar el proyecto de servidor al hospedar la aplicación con ASP.NET Core.

BlazorLas aplicaciones de WebAssembly se pueden depurar tanto en el explorador como en Visual Studio. Para más información, consulte Depuración de ASP.NET Core BlazorWebAssembly.

Tanto las aplicaciones Blazor Server como BlazorWebAssembly admiten Recarga activa en Visual Studio. Recarga activa es una característica que actualiza automáticamente los cambios realizados en una aplicación Blazor activa, en el explorador. Puede decidir si Recarga activa se habilita desde su icono en la barra de herramientas:

Visual Studio 2022: icono y elemento de menú de Recarga activa.

Al seleccionar el símbolo de intercalación situado junto al icono, se revelan opciones adicionales. Puede activar o desactivar Recarga activa, reiniciar la aplicación y decidir si Recarga activa debe producirse cada vez que se guarde un archivo.

Visual Studio 2022: elemento de menú de Recarga activa con opciones expandidas.

También puede acceder a opciones de configuración adicionales. El cuadro de diálogo de configuración permite especificar si Recarga activa debe habilitarse al depurar (junto con Editar y continuar), al iniciar sin depurar o al guardarse un archivo.

Visual Studio 2022: opciones de configuración de Recarga activa en el cuadro de diálogo

El "bucle interno del desarrollador" se ha simplificado de manera considerable con Recarga activa. Sin Recarga activa, lo habitual sería que los desarrolladores de Blazor tuvieran que reiniciar y volver a ejecutar la aplicación después de cada cambio, y desplazarse a la parte adecuada de la aplicación según fuera necesario. Con Recarga activa, se pueden realizar cambios en la aplicación en ejecución sin necesidad de reiniciar en la mayoría de los casos. Recarga activa incluso conserva el estado de las páginas, por lo que no es necesario tener que volver a escribir los valores del formulario o, de otro modo, volver a obtener la aplicación donde la necesite.