Integración y representación previa de componentes Razor de ASP.NET Core
Nota
Esta no es la versión más reciente de este artículo. Para la versión más reciente de este artículo, consulte la versión .NET 7.
En este artículo se explican los escenarios de integración de componentes Razor para aplicaciones Blazor, incluida la representación previa de componentes Razor en el servidor.
Importante
Los cambios en el marco de las diversas versiones de ASP.NET Core han dado lugar a distintos conjuntos de instrucciones en este artículo. Antes de seguir este artículo como guía, confirme que el selector de versión del documento de esta página coincida con la versión de ASP.NET Core que quiere usar para la aplicación.
Los componentes Razor se pueden integrar en aplicaciones Razor Pages y MVC de una soluciónBlazor WebAssembly hospedada. Cuando se representa la página o la vista, los componentes se pueden representar previamente al mismo tiempo.
La representación previa 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 pueden usar para calcular la clasificación de página.
Configuración de la solución
Configuración de la representación previa
Para configurar la representación previa de una aplicación Blazor WebAssembly hospedada:
Hospede la aplicación Blazor WebAssembly en una aplicación ASP.NET Core. Se puede agregar una aplicación Blazor WebAssembly independiente a una solución de ASP.NET Core, o bien se puede usar una aplicación Blazor WebAssembly hospedada creada a partir de la plantilla de proyecto de Blazor WebAssembly con la opción hospedada:
- Visual Studio: activa la casilla ASP.NET Core hospedado del cuadro de diálogo Información adicional al crear la aplicación Blazor WebAssembly. En los ejemplos de este artículo, la solución se llama
BlazorHosted
. - Shell de comandos de la CLI de Visual Studio Code/:NET:
dotnet new blazorwasm -ho
(use la opción-ho|--hosted
). Usa la opción-o|--output {LOCATION}
para crear una carpeta para la solución y establecer los espacios de nombres del proyecto de la solución. En los ejemplos de este artículo, la solución se llamaBlazorHosted
(dotnet new blazorwasm -ho -o BlazorHosted
).
En los ejemplos de este artículo, el nombre de la solución hospedada (nombre de ensamblado) es
BlazorHosted
. El espacio de nombres del proyecto de cliente esBlazorHosted.Client
y el espacio de nombres del proyecto de servidor esBlazorHosted.Server
.- Visual Studio: activa la casilla ASP.NET Core hospedado del cuadro de diálogo Información adicional al crear la aplicación Blazor WebAssembly. En los ejemplos de este artículo, la solución se llama
Elimine el archivo
wwwroot/index.html
del proyecto Client de Blazor WebAssembly.En el proyecto Client, elimine las líneas siguientes en
Program.cs
:- builder.RootComponents.Add<App>("#app"); - builder.RootComponents.Add<HeadOutlet>("head::after");
Agregue un archivo
_Host.cshtml
a la carpetaPages
del proyecto Server. Puede obtener los archivos de un proyecto creado a partir de la plantilla de Blazor Server mediante Visual Studio o la CLI de .NET con el comandodotnet new blazorserver -o BlazorServer
en un shell de comandos (la opción-o BlazorServer
crea una carpeta para el proyecto). Después de colocar los archivos en la carpetaPages
del proyecto Server, realice los cambios siguientes en los archivos.Realice los cambios siguientes en el archivo
_Host.cshtml
:Actualice el espacio de nombres
Pages
en la parte superior del archivo para que coincida con el espacio de nombres de las páginas de la aplicación Server . El marcador de posición{APP NAMESPACE}
del ejemplo siguiente representa el espacio de nombres de las páginas de la aplicación de donantes que proporcionó el archivo_Host.cshtml
:Eliminar:
- @namespace {APP NAMESPACE}.Pages
Agregue:
@namespace BlazorHosted.Server.Pages
Agregue una directiva
@using
para el proyecto Client en la parte superior del archivo:@using BlazorHosted.Client
Actualice los vínculos de la hoja de estilos para que apunten a las hojas de estilos del proyecto de WebAssembly. En el ejemplo siguiente, el espacio de nombres del proyecto de cliente es
BlazorHosted.Client
. El marcador de posición{APP NAMESPACE}
representa el espacio de nombres de la aplicación de donantes que proporcionó el archivo_Host.cshtml
. Actualice el asistente de etiquetas de componentes (etiqueta<component>
) para el componenteHeadOutlet
para representar previamente el componente.Eliminar:
- <link href="css/site.css" rel="stylesheet" /> - <link href="{APP NAMESPACE}.styles.css" rel="stylesheet" /> - <component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
Agregue:
<link href="css/app.css" rel="stylesheet" /> <link href="BlazorHosted.Client.styles.css" rel="stylesheet" /> <component type="typeof(HeadOutlet)" render-mode="WebAssemblyPrerendered" />
Nota
Deje como está el elemento
<link>
que solicita la hoja de estilos de arranquecss/bootstrap/bootstrap.min.css
.Actualice el origen del script de Blazor para usar el script de Blazor WebAssembly del lado cliente:
Eliminar:
- <script src="_framework/blazor.server.js"></script>
Agregue:
<script src="_framework/blazor.webassembly.js"></script>
Actualice el objeto
render-mode
del asistente de etiquetas de componentes para representar previamente el componenteApp
raíz con WebAssemblyPrerendered:Eliminar:
- <component type="typeof(App)" render-mode="ServerPrerendered" />
Agrega:
<component type="typeof(App)" render-mode="WebAssemblyPrerendered" />
Importante
La representación previa no se admite para los puntos de conexión de autenticación (segmento de ruta de acceso
/authentication/
). Para obtener más información, consulta Escenarios de seguridad adicionales en ASP.NET Core Blazor WebAssembly.
En el archivo
Program.cs
del proyecto Server, cambie el punto de conexión de reserva del archivoindex.html
a la página_Host.cshtml
:Eliminar:
- app.MapFallbackToFile("index.html");
Agrega:
app.MapFallbackToPage("/_Host");
Si los proyectos Client y Server usan uno o varios servicios comunes durante la representación previa, factorice los registros de servicio en un método al que se puede llamar desde ambos proyectos. Para obtener más información, consulta Inserción de dependencias de ASP.NET Core Blazor.
Ejecuta el proyecto Server . La aplicación Blazor WebAssembly hospedada se representa previamente en el proyecto Server para los clientes.
Configuración para insertar componentes Razor en páginas y vistas
En las secciones y ejemplos siguientes para insertar componentes Razor de la aplicación Blazor WebAssembly de Client en páginas y vistas de la aplicación de servidor se necesita configuración adicional.
El proyecto Server debe tener los siguientes archivos y carpetas.
Razor Pages:
Pages/Shared/_Layout.cshtml
Pages/Shared/_Layout.cshtml.css
Pages/_ViewImports.cshtml
Pages/_ViewStart.cshtml
MVC:
Views/Shared/_Layout.cshtml
Views/Shared/_Layout.cshtml.css
Views/_ViewImports.cshtml
Views/_ViewStart.cshtml
Los archivos anteriores se pueden obtener generando una aplicación a partir de las plantillas de proyecto de ASP.NET Core mediante:
- Herramientas de creación de proyectos de Visual Studio.
- Apertura de un shell de comandos y ejecución de
dotnet new webapp -o {PROJECT NAME}
(Razor Pages) odotnet new mvc -o {PROJECT NAME}
(MVC). La opción-o|--output
con un valor del marcador de posición{PROJECT NAME}
proporciona un nombre para la aplicación y crea una carpeta para la aplicación.
Actualiza los espacios de nombres del archivo _ViewImports.cshtml
importado para que coincidan con los que utiliza el proyecto Server que recibe los archivos.
Pages/_ViewImports.cshtml
(Razor Pages):
@using BlazorHosted.Server
@namespace BlazorHosted.Server.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
Views/_ViewImports.cshtml
(MVC):
@using BlazorHosted.Server
@using BlazorHosted.Server.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
Actualiza el archivo de diseño importado, que es Pages/Shared/_Layout.cshtml
para Razor Pages o Views/Shared/_Layout.cshtml
para MVC.
En primer lugar, elimina el título y la hoja de estilos del proyecto donante, que es RPDonor.styles.css
en el ejemplo siguiente. El marcador de posición {PROJECT NAME}
representa el nombre de la aplicación del proyecto de donantes.
- <title>@ViewData["Title"] - {PROJECT NAME}</title>
- <link rel="stylesheet" href="~/RPDonor.styles.css" asp-append-version="true" />
Incluye los estilos del proyecto Client en el archivo de diseño. En el ejemplo siguiente, el espacio de nombres del proyecto Client es BlazorHosted.Client
. El elemento <title>
se puede actualizar al mismo tiempo.
Coloca las siguientes líneas en el contenido <head>
del archivo de diseño:
<title>@ViewData["Title"] - BlazorHosted</title>
<link href="css/app.css" rel="stylesheet" />
<link rel="stylesheet" href="BlazorHosted.Client.styles.css" asp-append-version="true" />
<component type="typeof(HeadOutlet)" render-mode="WebAssemblyPrerendered" />
El diseño importado contiene dos Home
(página Index
) y vínculos de navegación Privacy
. Para que los vínculos Home
apunten a la aplicación Blazor WebAssembly hospedada, cambia los hipervínculos:
- <a class="navbar-brand" asp-area="" asp-page="/Index">{PROJECT NAME}</a>
+ <a class="navbar-brand" href="/">BlazorHosted</a>
- <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
+ <a class="nav-link text-dark" href="/">Home</a>
En un archivo de diseño de MVC:
- <a class="navbar-brand" asp-area="" asp-controller="Home"
- asp-action="Index">{PROJECT NAME}</a>
+ <a class="navbar-brand" href="/">BlazorHosted</a>
- <a class="nav-link text-dark" asp-area="" asp-controller="Home"
- asp-action="Index">Home</a>
+ <a class="nav-link text-dark" href="/">Home</a>
Actualiza el nombre de la aplicación del elemento <footer>
. El ejemplo siguiente usa el nombre de aplicación BlazorHosted
:
- © {DATE} - {DONOR NAME} - <a asp-area="" asp-page="/Privacy">Privacy</a>
+ © {DATE} - BlazorHosted - <a asp-area="" asp-page="/Privacy">Privacy</a>
En el ejemplo anterior, el marcador de posición {DATE}
representa la fecha de copyright de una aplicación generada a partir de la plantilla de proyecto Razor Pages o MVC.
Para que el vínculo Privacy
dirija a una página de privacy (Razor Pages), agrega una página de privacy al proyecto Server.
Pages/Privacy.cshtml
en el proyecto Server :
@page
@model PrivacyModel
@{
ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>
<p>Use this page to detail your site's privacy policy.</p>
Para una vista de privacy basada en MVC, crea una vista de privacy en el proyecto Server.
View/Home/Privacy.cshtml
en el proyecto Server :
@{
ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>
<p>Use this page to detail your site's privacy policy.</p>
En el controlador Home
de la aplicación MVC, devuelve la vista.
Agrega el código siguiente a Controllers/HomeController.cs
:
public IActionResult Privacy()
{
return View();
}
Si importas archivos desde una aplicación de donantes, asegúrate de actualizar los espacios de nombres de los archivos para que coincidan con el del proyecto Server (por ejemplo, BlazorHosted.Server
).
Importa los recursos estáticos al proyecto Server desde la carpeta wwwroot
del proyecto de donantes:
- Carpeta
wwwroot/css
y su contenido - Carpeta
wwwroot/js
y su contenido - Carpeta
wwwroot/lib
y su contenido
Si el proyecto de donantes se crea a partir de una plantilla de proyecto de ASP.NET Core y los archivos no se han modificado, puedes copiar toda la carpeta wwwroot
de dicho proyecto en el proyecto Server y quitar el archivo de icono favicon.
Advertencia
Evita colocar el recurso estático en las carpetas wwwroot
de Client y Server. Si está presente el mismo archivo en ambas carpetas, se produce una excepción porque el recurso estático comparte la misma ruta de acceso raíz web. Por lo tanto, hospeda un recurso estático en una de las carpetas wwwroot
, no en ambas.
Después de adoptar la configuración anterior, inserta componentes Razor en páginas o vistas del proyecto Server . Usa las instrucciones de las secciones siguientes de este artículo:
- Representación de componentes en una página o vista con la aplicación auxiliar de etiquetas de componentes
- Representación de componentes en una página o vista con un selector de CSS
Representación de componentes en una página o vista con la aplicación auxiliar de etiquetas de componentes
Después de configurar la solución, incluida la configuración adicional, el asistente de etiquetas de componentes admite dos modos de representación para representar un componente de una aplicación Blazor WebAssembly en una página o vista:
En el siguiente ejemplo de Razor Pages, el componente Counter
se representa en una página. Para convertir el componente en interactivo, el script Blazor WebAssembly se incluye en la sección de representación de la página. Si deseas evitar el uso del espacio de nombres completo del componente Counter
con el asistente de etiquetas de componentes ({ASSEMBLY NAME}.Pages.Counter
), agrega una directiva @using
para el espacio de nombres Pages
del proyecto de cliente. En el ejemplo siguiente, el espacio de nombres del proyecto Client es BlazorHosted.Client
.
En el proyecto Server , Pages/RazorPagesCounter1.cshtml
:
@page
@using BlazorHosted.Client.Pages
<component type="typeof(Counter)" render-mode="WebAssemblyPrerendered" />
@section Scripts {
<script src="_framework/blazor.webassembly.js"></script>
}
Ejecuta el proyecto Server . Ve a la página Razor en /razorpagescounter1
. El componente Counter
representado previamente se inserta en la página.
RenderMode configura si el componente:
- Se representa previamente en la página.
- Se representa como HTML estático en la página o si incluye la información necesaria para arrancar una aplicación Blazor desde el agente de usuario.
Para obtener más información sobre el asistente de etiquetas de componentes, como pasar parámetros y configurar RenderMode, consulta Asistente de etiquetas de componente en ASP.NET Core.
Puede ser necesario realizar trabajo adicional en función de los recursos estáticos que usan los componentes y de cómo se organizan las páginas de diseño en una aplicación. Normalmente, los scripts se agregan a la sección de representación de Scripts
de una vista o una página, y las hojas de estilos se agregan al contenido del elemento <head>
del diseño.
Establecer contenido secundario a través de un fragmento de representación
El asistente de etiquetas de componente no admite la recepción de un delegado RenderFragment
para el contenido secundario (por ejemplo, param-ChildContent="..."
). Se recomienda crear un componente Razor (.razor
) que haga referencia al componente que se desea representar con el contenido secundario que se desea pasar y, después, invocar el componente Razor desde la página o vista.
Asegúrate de que los componentes representados previamente de nivel superior no se recortan en la publicación.
Si un asistente de etiquetas de componente hace referencia directamente a un componente de una biblioteca que está sujeta a recortes en la publicación, el componente podría recortarse durante la publicación porque no hay referencias a él desde el código de la aplicación del lado cliente. Como resultado, el componente no se representa previamente y deja un espacio en blanco en la salida. Si esto ocurre, indica al recortador que conserve el componente de biblioteca agregando un atributo DynamicDependency
attribute cualquier clase de la aplicación del lado cliente. Para conservar un componente denominado SomeLibraryComponentToBePreserved
, agrega lo siguiente a cualquier componente:
@using System.Diagnostics.CodeAnalysis
@attribute [DynamicDependency(DynamicallyAccessedMemberTypes.All,
typeof(SomeLibraryComponentToBePreserved))]
Normalmente, el enfoque anterior no es necesario porque, en la mayoría de los casos, la aplicación representa previamente sus componentes (que no se recortan), y estos, a su vez, hacen referencia a componentes de bibliotecas (lo que hace que tampoco se recorten). Usa solo DynamicDependency
explícitamente para representar previamente un componente de biblioteca directamente cuando esté sujeta a recorte.
Representación de componentes en una página o vista con un selector de CSS
Después de configurar la solución, incluida la configuración adicional, agrega los componentes raíz al proyecto Client de una solución de Blazor WebAssembly hospedada en el archivo Program.cs
. En el siguiente ejemplo, el componente Counter
se declara como un componente raíz con un selector de CSS que selecciona el elemento con el objeto id
que coincide con counter-component
. En el ejemplo siguiente, el espacio de nombres del proyecto Client es BlazorHosted.Client
.
En el archivo Program.cs
del proyecto Client , agrega el espacio de nombres de los componentes Razor del proyecto en la parte superior del archivo:
using BlazorHosted.Client.Pages;
Después de establecer el elemento builder
en Program.cs
, agrega el componente Counter
como componente raíz:
builder.RootComponents.Add<Counter>("#counter-component");
En el siguiente ejemplo de Razor Pages, el componente Counter
se representa en una página. Para convertir el componente en interactivo, el script Blazor WebAssembly se incluye en la sección de representación de la página.
En el proyecto Server , Pages/RazorPagesCounter2.cshtml
:
@page
<div id="counter-component">Loading...</div>
@section Scripts {
<script src="_framework/blazor.webassembly.js"></script>
}
Ejecuta el proyecto Server . Ve a la página Razor en /razorpagescounter2
. El componente Counter
representado previamente se inserta en la página.
Puede ser necesario realizar trabajo adicional en función de los recursos estáticos que usan los componentes y de cómo se organizan las páginas de diseño en una aplicación. Normalmente, los scripts se agregan a la sección de representación de Scripts
de una vista o una página, y las hojas de estilos se agregan al contenido del elemento <head>
del diseño.
Nota
En el ejemplo anterior se produce una excepción JSException si una aplicación Blazor WebAssembly se representa previamente y se integra en una Razoraplicación Pages o MVC a la vez con el uso de un selector de CSS. Al navegar a uno de los componentes Razor del proyecto Client o a una página o vista de Server con un componente insertado, se producen una o varias excepciones JSException.
Este comportamiento es normal porque la representación previa y la integración de una aplicación Blazor WebAssembly con componentes de Razor enrutables no son compatibles con el uso de selectores de CSS.
Si has estado trabajando con los ejemplos de las secciones anteriores y solo deseas ver que el selector de CSS funciona en la aplicación de ejemplo, convierte en comentario la especificación del componente raíz App
del archivo Program.cs
del proyecto Client :
- builder.RootComponents.Add<App>("#app");
+ //builder.RootComponents.Add<App>("#app");
Ve a la página o vista con el componente Razor insertado que usa un selector de CSS (por ejemplo, /razorpagescounter2
del ejemplo anterior). La página o vista se carga con el componente insertado y el componente insertado funciona según lo previsto.
Los componentes Razor se pueden integrar en aplicaciones de Razor Pages y MVC. Cuando se representa la página o la vista, los componentes se pueden representar previamente al mismo tiempo.
La representación previa 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 pueden usar para calcular la clasificación de página.
Después de configurar el proyecto, usa la guía que aparece en las secciones siguientes en función de los requisitos del proyecto:
- Para los componentes que se pueden enrutar directamente desde las solicitudes del usuario. Sigue estas instrucciones cuando los visitantes puedan hacer una solicitud HTTP en el explorador para un componente con una directiva
@page
. - Para los componentes que no se pueden enrutar directamente desde las solicitudes del usuario, consulta la sección Representación de componentes a partir de una página o vista. Sigue estas instrucciones cuando la aplicación inserte componentes en páginas y vistas existentes con el asistente de etiquetas de componente.
Configuración
Sigue estas instrucciones para integrar componentes Razor en páginas y vistas de una aplicación Razor Pages o MVC existente.
Agrega un archivo imports a la carpeta raíz del proyecto con el contenido siguiente. Cambia el marcador de posición
{APP NAMESPACE}
al espacio de nombres del proyecto._Imports.razor
:@using System.Net.Http @using Microsoft.AspNetCore.Authorization @using Microsoft.AspNetCore.Components.Authorization @using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Web @using Microsoft.AspNetCore.Components.Web.Virtualization @using Microsoft.JSInterop @using {APP NAMESPACE}
En el archivo de diseño del proyecto (
Pages/Shared/_Layout.cshtml
en aplicaciones Razor Pages oViews/Shared/_Layout.cshtml
en aplicaciones MVC):Agrega la siguiente etiqueta
<base>
y el asistente de etiqueta de componente HeadOutlet al elemento<head>
:<base href="~/" /> <component type="typeof(Microsoft.AspNetCore.Components.Web.HeadOutlet)" render-mode="ServerPrerendered" />
El valor
href
(la ruta de acceso base de la aplicación) del ejemplo anterior da por hecho que la aplicación reside en la ruta de acceso URL raíz (/
). Si la aplicación es una subaplicación, sigue las instrucciones de la sección Ruta base de la aplicación del artículo Hospedaje e implementación de ASP.NET Core Blazor.El componente HeadOutlet se usa para representar el contenido principal (
<head>
) para los títulos de página (componente PageTitle) y otros elementos principales (componente HeadContent) establecidos por componentes Razor. Para obtener más información, consulta Control del contenido principal en aplicaciones de ASP.NET Core Blazor.Agrega una etiqueta
<script>
para el scriptblazor.server.js
inmediatamente antes de la sección de representaciónScripts
(@await RenderSectionAsync(...)
):<script src="_framework/blazor.server.js"></script>
El marco agrega el script
blazor.server.js
a la aplicación. No es necesario agregar manualmente un archivo de scriptblazor.server.js
a la aplicación.
Nota:
Normalmente, el diseño se carga a través de un archivo
_ViewStart.cshtml
.Registra los servicios Blazor Server en
Program.cs
, donde se registran los servicios:builder.Services.AddServerSideBlazor();
Agrega el punto de conexión del centro Blazor a los puntos de conexión de
Program.cs
donde se asignan las rutas. Coloca la siguiente línea después de la llamada aMapRazorPages
( Razor Pages) oMapControllerRoute
(MVC):app.MapBlazorHub();
Integra los componentes en cualquier página o vista. Por ejemplo, agrega un componente
Counter
a la carpetaShared
del proyecto.Pages/Shared/Counter.razor
(Razor Pages) oViews/Shared/Counter.razor
(MVC):<h1>Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
Razor Pages:
En la página
Index
del proyecto de una aplicación Razor Pages, agrega el espacio de nombres del componenteCounter
e inserta el componente en la página. Cuando se carga la páginaIndex
, el componenteCounter
se representa previamente en ella. En el ejemplo siguiente, reemplaza el marcador de posición{APP NAMESPACE}
por el espacio de nombres del proyecto.Pages/Index.cshtml
:@page @using {APP NAMESPACE}.Pages.Shared @model IndexModel @{ ViewData["Title"] = "Home page"; } <component type="typeof(Counter)" render-mode="ServerPrerendered" />
MVC:
En la vista
Index
del proyecto de una aplicación MVC, agrega el espacio de nombres del componenteCounter
e inserta el componente en la vista. Cuando se carga la vistaIndex
, el componenteCounter
se representa previamente en ella. En el ejemplo siguiente, reemplaza el marcador de posición{APP NAMESPACE}
por el espacio de nombres del proyecto.Views/Home/Index.cshtml
:@using {APP NAMESPACE}.Views.Shared @{ ViewData["Title"] = "Home Page"; } <component type="typeof(Counter)" render-mode="ServerPrerendered" />
Para obtener más información, consulta la sección Representación de componentes a partir de una página o vista.
Uso de componentes enrutables en una aplicación Razor Pages
Esta sección pertenece a la incorporación de componentes que se pueden enrutar directamente desde las solicitudes del usuario.
Para admitir componentes Razor enrutables en aplicaciones Razor Pages:
Sigue las instrucciones de la sección Configuración.
Agrega un componente
App
a la raíz del proyecto con el contenido siguiente.App.razor
:@using Microsoft.AspNetCore.Components.Routing <Router AppAssembly="typeof(App).Assembly"> <Found Context="routeData"> <RouteView RouteData="routeData" /> </Found> <NotFound> <PageTitle>Not found</PageTitle> <p role="alert">Sorry, there's nothing at this address.</p> </NotFound> </Router>
Agrega una página
_Host
al proyecto con el contenido siguiente. Reemplaza el marcador de posición{APP NAMESPACE}
por el espacio de nombres de la aplicación.Pages/_Host.cshtml
:@page @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers <component type="typeof(App)" render-mode="ServerPrerendered" />
Nota:
En el ejemplo anterior se supone que el diseño de la aplicación representa el componente HeadOutlet y el script Blazor (
_framework/blazor.server.js
). Para obtener más información, consulta la sección Configuración.RenderMode configura si el componente
App
:- Se representa previamente en la página.
- Se representa como HTML estático en la página o si incluye la información necesaria para arrancar una aplicación Blazor desde el agente de usuario.
Para obtener más información sobre el asistente de etiquetas de componentes, como pasar parámetros y configurar RenderMode, consulta Asistente de etiquetas de componente en ASP.NET Core.
En los puntos de conexión
Program.cs
, agrega una ruta de prioridad baja para la página_Host
como último punto de conexión:app.MapFallbackToPage("/_Host");
Agrega componentes enrutables al proyecto. El ejemplo siguiente es un componente
RoutableCounter
basado en el componenteCounter
de las plantillas de proyecto de Blazor.Pages/RoutableCounter.razor
:@page "/routable-counter" <PageTitle>Routable Counter</PageTitle> <h1>Routable Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
Ejecuta el proyecto y ve al componente
RoutableCounter
enrutable en/routable-counter
.
Para obtener más información sobre los espacios de nombres, consulta la sección Espacios de nombres de componentes.
Uso de componentes enrutables en una aplicación MVC
Esta sección pertenece a la incorporación de componentes que se pueden enrutar directamente desde las solicitudes del usuario.
Para admitir componentes Razor enrutables en aplicaciones MVC, haga lo siguiente:
Sigue las instrucciones de la sección Configuración.
Agrega un componente
App
a la raíz del proyecto con el contenido siguiente.App.razor
:@using Microsoft.AspNetCore.Components.Routing <Router AppAssembly="typeof(App).Assembly"> <Found Context="routeData"> <RouteView RouteData="routeData" /> </Found> <NotFound> <PageTitle>Not found</PageTitle> <p role="alert">Sorry, there's nothing at this address.</p> </NotFound> </Router>
Agrega una vista
_Host
al proyecto con el contenido siguiente. Reemplaza el marcador de posición{APP NAMESPACE}
por el espacio de nombres de la aplicación.Views/Home/_Host.cshtml
:@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers <component type="typeof(App)" render-mode="ServerPrerendered" />
Nota:
En el ejemplo anterior se supone que el diseño de la aplicación representa el componente HeadOutlet y el script Blazor (
_framework/blazor.server.js
). Para obtener más información, consulta la sección Configuración.RenderMode configura si el componente
App
:- Se representa previamente en la página.
- Se representa como HTML estático en la página o si incluye la información necesaria para arrancar una aplicación Blazor desde el agente de usuario.
Para obtener más información sobre el asistente de etiquetas de componentes, como pasar parámetros y configurar RenderMode, consulta Asistente de etiquetas de componente en ASP.NET Core.
Agrega una acción al controlador Home.
Controllers/HomeController.cs
:public IActionResult Blazor() { return View("_Host"); }
En los puntos de conexión
Program.cs
, agrega una ruta de prioridad baja para la acción del controlador que devuelva la vista_Host
:app.MapFallbackToController("Blazor", "Home");
Crea una carpeta
Pages
en la aplicación MVC y agregue componentes enrutables. El ejemplo siguiente es un componenteRoutableCounter
basado en el componenteCounter
de las plantillas de proyecto de Blazor.Pages/RoutableCounter.razor
:@page "/routable-counter" <PageTitle>Routable Counter</PageTitle> <h1>Routable Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
Ejecuta el proyecto y ve al componente
RoutableCounter
enrutable en/routable-counter
.
Para obtener más información sobre los espacios de nombres, consulta la sección Espacios de nombres de componentes.
Representación de componentes a partir de una página o vista
Esta sección pertenece a la adición de componentes a páginas o vistas, donde los componentes no son enrutables directamente desde las solicitudes del usuario.
Para representar un componente a partir de una página o vista, usa el asistente de etiquetas de componente.
Representación de componentes interactivos con estado
Los componentes interactivos con estado se pueden agregar a una página de Razor o una vista.
Cuando se representa la página o la vista:
- El componente se representa previamente con la página o la vista.
- Se pierde el estado inicial del componente que se usa para la representación previa.
- Cuando se establece la conexión SignalR, se crea un estado del componente.
La siguiente página de Razor representa un componente Counter
:
<h1>Razor Page</h1>
<component type="typeof(Counter)" render-mode="ServerPrerendered"
param-InitialValue="InitialValue" />
@functions {
[BindProperty(SupportsGet=true)]
public int InitialValue { get; set; }
}
Para obtener más información, consulta Asistente de etiquetas de componente en ASP.NET Core.
Representación de componentes no interactivos
En la siguiente página de Razor, el componente Counter
se representa de forma estática con un valor inicial que se especifica mediante un formulario. Como el componente se representa de forma estática, no es interactivo:
<h1>Razor Page</h1>
<form>
<input type="number" asp-for="InitialValue" />
<button type="submit">Set initial value</button>
</form>
<component type="typeof(Counter)" render-mode="Static"
param-InitialValue="InitialValue" />
@functions {
[BindProperty(SupportsGet=true)]
public int InitialValue { get; set; }
}
Para obtener más información, consulta Asistente de etiquetas de componente en ASP.NET Core.
Espacios de nombres de componentes
Si usas una carpeta personalizada para contener los componentes Razor del proyecto, agrega el espacio de nombres que representa la carpeta a la página o vista, o bien al archivo _ViewImports.cshtml
. En el ejemplo siguiente:
- Los componentes se almacenan en la carpeta
Components
del proyecto. - El marcador de posición
{APP NAMESPACE}
es el espacio de nombres del proyecto.Components
representa el nombre de la carpeta.
@using {APP NAMESPACE}.Components
El archivo _ViewImports.cshtml
se encuentra en la carpeta Pages
de una aplicación Razor Pages o en la carpeta Views
de una aplicación de MVC.
Para obtener más información, consulta Componentes de ASP.NET Core Razor.
Conservación del estado previamente representado
Si no se conserva el estado representado previamente, se pierde el estado usado durante la representación previa, por lo que se debe volver a crear una vez que la aplicación se haya cargado por completo. Si algún estado se configura de forma asincrónica, puede que la interfaz de usuario representada previamente parpadee mientras se sustituye por marcadores de posición temporales y se vuelve a representar.
Para conservar el estado de los componentes representados previamente, usa el asistente de etiquetas de conservación del estado del componente (origen de referencia). Agrega la etiqueta del asistente de etiquetas, <persist-component-state />
, dentro de la etiqueta de cierre </body>
de la página _Host
en una aplicación que representa previamente los componentes.
Nota:
Los vínculos de la documentación al origen de referencia de .NET cargan normalmente la rama predeterminada del repositorio, que representa el desarrollo actual para la próxima versión de .NET. Para seleccionar una etiqueta de una versión específica, usa la lista desplegable Cambiar ramas o etiquetas. Para obtener más información, consulta Procedimientos para seleccionar una etiqueta de versión de código fuente de ASP.NET Core (dotnet/AspNetCore.Docs #26205).
En Pages/_Host.cshtml
de Blazor de las aplicaciones que están prerrenderizadas (WebAssemblyPrerendered
) en una aplicación de Blazor WebAssembly hospedada o ServerPrerendered
en una aplicación de Blazor Server:
<body>
...
<persist-component-state />
</body>
En la aplicación, decide qué estado quiere conservar mediante el servicio PersistentComponentState. PersistentComponentState.RegisterOnPersisting
registra una devolución de llamada para conservar el estado del componente antes de que se pause la aplicación. El estado se recupera cuando se reanuda la aplicación.
En el ejemplo siguiente:
- El marcador de posición
{TYPE}
representa el tipo de datos que se va a conservar (por ejemplo,WeatherForecast[]
). - El marcador de posición
{TOKEN}
es una cadena de identificador de estado (por ejemplo,fetchdata
).
@implements IDisposable
@inject PersistentComponentState ApplicationState
...
@code {
private {TYPE} data;
private PersistingComponentStateSubscription persistingSubscription;
protected override async Task OnInitializedAsync()
{
persistingSubscription =
ApplicationState.RegisterOnPersisting(PersistData);
if (!ApplicationState.TryTakeFromJson<{TYPE}>(
"{TOKEN}", out var restored))
{
data = await ...;
}
else
{
data = restored!;
}
}
private Task PersistData()
{
ApplicationState.PersistAsJson("{TOKEN}", data);
return Task.CompletedTask;
}
void IDisposable.Dispose()
{
persistingSubscription.Dispose();
}
}
El ejemplo siguiente es una versión actualizada del componente FetchData
en una aplicación de Blazor WebAssembly hospedada basada en la plantilla de proyecto Blazor. El componente WeatherForecastPreserveState
conserva el estado de previsión meteorológica durante la representación previa y, después, recupera el estado para inicializar el componente. El Asistente para la conservación de etiquetas de estado de componente conserva el estado del componente después de todas las invocaciones de componentes.
Pages/WeatherForecastPreserveState.razor
:
@page "/weather-forecast-preserve-state"
@using BlazorSample.Shared
@implements IDisposable
@inject IWeatherForecastService WeatherForecastService
@inject PersistentComponentState ApplicationState
<PageTitle>Weather Forecast</PageTitle>
<h1>Weather forecast</h1>
<p>This component demonstrates fetching data from the server.</p>
@if (forecasts == null)
{
<p><em>Loading...</em></p>
}
else
{
<table class="table">
<thead>
<tr>
<th>Date</th>
<th>Temp. (C)</th>
<th>Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
@foreach (var forecast in forecasts)
{
<tr>
<td>@forecast.Date.ToShortDateString()</td>
<td>@forecast.TemperatureC</td>
<td>@forecast.TemperatureF</td>
<td>@forecast.Summary</td>
</tr>
}
</tbody>
</table>
}
@code {
private WeatherForecast[] forecasts = Array.Empty<WeatherForecast>();
private PersistingComponentStateSubscription persistingSubscription;
protected override async Task OnInitializedAsync()
{
persistingSubscription =
ApplicationState.RegisterOnPersisting(PersistForecasts);
if (!ApplicationState.TryTakeFromJson<WeatherForecast[]>(
"fetchdata", out var restored))
{
forecasts =
await WeatherForecastService.GetForecastAsync(DateOnly.FromDateTime(DateTime.Now));
}
else
{
forecasts = restored!;
}
}
private Task PersistForecasts()
{
ApplicationState.PersistAsJson("fetchdata", forecasts);
return Task.CompletedTask;
}
void IDisposable.Dispose()
{
persistingSubscription.Dispose();
}
}
Al inicializar componentes con el mismo estado que se usa durante la representación previa, los pasos de inicialización costosos solo se ejecutan una vez. La interfaz de usuario representada también coincide con la que se ha representado previamente, por lo que no se produce ningún parpadeo en el explorador.
El estado preenderado persistente se transfiere al cliente, donde se usa para restaurar el estado del componente. ASP.NET Protección de datos principales garantiza que los datos se transfieren de forma segura en Blazor Server las aplicaciones. Para la representación previa en una aplicación hospedada Blazor WebAssembly , los datos se exponen al explorador y no deben contener información confidencial y privada.
Recursos de Blazor WebAssembly adicionales
- Administración de estados: control de la representación previa
- Compatibilidad con la representación previa con la carga diferida de ensamblados
- Temas del ciclo de vida de los componentes Razor relacionados con la representación previa
- Inicialización de componentes (
OnInitialized{Async}
) - Después de representar el componente (
OnAfterRender{Async}
) - Reconexión con estado después de la representación previa: aunque el contenido de la sección se centra en Blazor Server y en la reconexión de SignalR con estado, el escenario de representación previa de las aplicaciones Blazor WebAssembly hospedadas (WebAssemblyPrerendered) conlleva condiciones y enfoques similares para evitar ejecutar dos veces el código del desarrollador. Para preservar el estado durante la ejecución del código de inicialización mientras se realiza la renderización previa, consulta la sección Persistir el estado de la renderización previa de este artículo.
- Representación previa con interoperabilidad de JavaScript
- Inicialización de componentes (
- Aspectos de autenticación y autorización relacionados con la representación previa
- Hospedaje e implementación: Blazor WebAssembly
- Control de errores: representación previa
- OnNavigateAsync se ejecuta dos veces al representar previamente: control de eventos de navegación asincrónicos con
OnNavigateAsync
Tamaño de estado antes de la representación y límite de tamaño del mensaje SignalR
Un tamaño grande de estado anterior a la representación puede superar el límite de tamaño del mensaje de circuito SignalR, lo que da como resultado lo siguiente:
- El circuito SignalR no se puede inicializar con un error en el cliente: Circuit host not initialized.
- La interfaz de usuario de reconexión del cliente aparece cuando se produce un error en el circuito. No es posible la recuperación.
Para resolver el problema, usa uno de los enfoques siguientes:
- Reduce la cantidad de datos que se están colocando en el estado anterior a la representación.
- Aumenta el límite de tamaño del mensajeSignalR. ADVERTENCIA: Aumentar el límite puede aumentar el riesgo de ataques por denegación de servicio (DoS).
Recursos de Blazor Server adicionales
- Administración de estados: control de la representación previa
- Temas del ciclo de vida de los componentes Razor relacionados con la representación previa
- Autenticación y autorización: aspectos generales
- Control de errores: representación previa de
- Hospedaje e implementación: Blazor Server
- Mitigación de amenazas: scripting entre sitios (XSS)
- OnNavigateAsync se ejecuta dos veces al representar previamente: control de eventos de navegación asincrónicos con
OnNavigateAsync
Los componentes Razor se pueden integrar en aplicaciones Razor Pages y MVC de una soluciónBlazor WebAssembly hospedada. Cuando se representa la página o la vista, los componentes se pueden representar previamente al mismo tiempo.
La representación previa 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 pueden usar para calcular la clasificación de página.
Configuración de la solución
Configuración de la representación previa
Para configurar la representación previa de una aplicación Blazor WebAssembly hospedada:
Hospede la aplicación Blazor WebAssembly en una aplicación ASP.NET Core. Se puede agregar una aplicación Blazor WebAssembly independiente a una solución de ASP.NET Core, o bien se puede usar una aplicación Blazor WebAssembly hospedada creada a partir de la plantilla de proyecto de Blazor WebAssembly con la opción hospedada:
- Visual Studio: activa la casilla ASP.NET Core hospedado del cuadro de diálogo Información adicional al crear la aplicación Blazor WebAssembly. En los ejemplos de este artículo, la solución se llama
BlazorHosted
. - Shell de comandos de la CLI de Visual Studio Code/:NET:
dotnet new blazorwasm -ho
(use la opción-ho|--hosted
). Usa la opción-o|--output {LOCATION}
para crear una carpeta para la solución y establecer los espacios de nombres del proyecto de la solución. En los ejemplos de este artículo, la solución se llamaBlazorHosted
(dotnet new blazorwasm -ho -o BlazorHosted
).
En los ejemplos de este artículo, el espacio de nombres del proyecto de cliente es
BlazorHosted.Client
y el espacio de nombres del proyecto de servidor esBlazorHosted.Server
.- Visual Studio: activa la casilla ASP.NET Core hospedado del cuadro de diálogo Información adicional al crear la aplicación Blazor WebAssembly. En los ejemplos de este artículo, la solución se llama
Elimine el archivo
wwwroot/index.html
del proyecto Client de Blazor WebAssembly.En el proyecto Client, elimine las líneas siguientes en
Program.cs
:- builder.RootComponents.Add<App>("#app"); - builder.RootComponents.Add<HeadOutlet>("head::after");
Agregue archivos
_Host.cshtml
y_Layout.cshtml
a la carpetaPages
del proyecto Server . Puede obtener los archivos de un proyecto creado a partir de la plantilla de Blazor Server mediante Visual Studio o la CLI de .NET con el comandodotnet new blazorserver -o BlazorServer
en un shell de comandos (la opción-o BlazorServer
crea una carpeta para el proyecto). Después de colocar los archivos en la carpetaPages
del proyecto Server, realice los cambios siguientes en los archivos.Importante
El uso de una página de diseño (
_Layout.cshtml
) con un asistente de etiquetas de componente para un componente HeadOutlet es necesario para controlar el contenido<head>
, como el título de la página (componente PageTitle) y otros elementos principales (componente HeadContent). Para más información, vea Control del contenido principal en aplicaciones Blazor de ASP.NET Core.Realice los cambios siguientes en el archivo
_Layout.cshtml
:Actualice el espacio de nombres
Pages
en la parte superior del archivo para que coincida con el espacio de nombres de las páginas de la aplicación Server . El marcador de posición{APP NAMESPACE}
del ejemplo siguiente representa el espacio de nombres de las páginas de la aplicación de donantes que proporcionó el archivo_Layout.cshtml
:Eliminar:
- @namespace {APP NAMESPACE}.Pages
Agregue:
@namespace BlazorHosted.Server.Pages
Agregue una directiva
@using
para el proyecto Client en la parte superior del archivo:@using BlazorHosted.Client
Actualice los vínculos de la hoja de estilos para que apunten a las hojas de estilos del proyecto de WebAssembly. En el ejemplo siguiente, el espacio de nombres del proyecto de cliente es
BlazorHosted.Client
. El marcador de posición{APP NAMESPACE}
representa el espacio de nombres de la aplicación de donantes que proporcionó el archivo_Layout.cshtml
. Actualice el asistente de etiquetas de componentes (etiqueta<component>
) para el componenteHeadOutlet
para representar previamente el componente.Eliminar:
- <link href="css/site.css" rel="stylesheet" /> - <link href="{APP NAMESPACE}.styles.css" rel="stylesheet" /> - <component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
Agregue:
<link href="css/app.css" rel="stylesheet" /> <link href="BlazorHosted.Client.styles.css" rel="stylesheet" /> <component type="typeof(HeadOutlet)" render-mode="WebAssemblyPrerendered" />
Nota
Deje como está el elemento
<link>
que solicita la hoja de estilos de arranquecss/bootstrap/bootstrap.min.css
.Actualice el origen del script de Blazor para usar el script de Blazor WebAssembly del lado cliente:
Eliminar:
- <script src="_framework/blazor.server.js"></script>
Agregue:
<script src="_framework/blazor.webassembly.js"></script>
En el archivo
_Host.cshtml
:Cambie el espacio de nombres
Pages
por el del proyecto Client . El marcador de posición{APP NAMESPACE}
representa el espacio de nombres de las páginas de la aplicación de donantes que proporcionó el archivo_Host.cshtml
:Eliminar:
- @namespace {APP NAMESPACE}.Pages
Agregue:
@namespace BlazorHosted.Client
Actualice el objeto
render-mode
del asistente de etiquetas de componentes para representar previamente el componenteApp
raíz con WebAssemblyPrerendered:Eliminar:
- <component type="typeof(App)" render-mode="ServerPrerendered" />
Agrega:
<component type="typeof(App)" render-mode="WebAssemblyPrerendered" />
Importante
La representación previa no se admite para los puntos de conexión de autenticación (segmento de ruta de acceso
/authentication/
). Para más información, vea Escenarios de seguridad adicionales de Blazor WebAssembly en ASP.NET Core.
En la asignación de puntos de conexión del proyecto Server de
Program.cs
, cambie la reserva del archivoindex.html
por la página_Host.cshtml
:Eliminar:
- app.MapFallbackToFile("index.html");
Agrega:
app.MapFallbackToPage("/_Host");
Si los proyectos Client y Server usan uno o varios servicios comunes durante la representación previa, factorice los registros de servicio en un método al que se puede llamar desde ambos proyectos. Para obtener más información, consulta Inserción de dependencias de ASP.NET Core Blazor.
Ejecuta el proyecto Server . La aplicación Blazor WebAssembly hospedada se representa previamente en el proyecto Server para los clientes.
Configuración para insertar componentes Razor en páginas y vistas
En las secciones y ejemplos siguientes para insertar componentes Razor de la aplicación Blazor WebAssembly de Client en páginas y vistas de la aplicación de servidor se necesita configuración adicional.
El proyecto Server debe tener los siguientes archivos y carpetas.
Razor Pages:
Pages/Shared/_Layout.cshtml
Pages/Shared/_Layout.cshtml.css
Pages/_ViewImports.cshtml
Pages/_ViewStart.cshtml
MVC:
Views/Shared/_Layout.cshtml
Views/Shared/_Layout.cshtml.css
Views/_ViewImports.cshtml
Views/_ViewStart.cshtml
Importante
El uso de una página de diseño (_Layout.cshtml
) con un asistente de etiquetas de componente para un componente HeadOutlet es necesario para controlar el contenido <head>
, como el título de la página (componente PageTitle) y otros elementos principales (componente HeadContent). Para más información, vea Control del contenido principal en aplicaciones Blazor de ASP.NET Core.
Los archivos anteriores se pueden obtener generando una aplicación a partir de las plantillas de proyecto de ASP.NET Core mediante:
- Herramientas de creación de proyectos de Visual Studio.
- Apertura de un shell de comandos y ejecución de
dotnet new webapp -o {PROJECT NAME}
(Razor Pages) odotnet new mvc -o {PROJECT NAME}
(MVC). La opción-o|--output
con un valor del marcador de posición{PROJECT NAME}
proporciona un nombre para la aplicación y crea una carpeta para la aplicación.
Actualiza los espacios de nombres del archivo _ViewImports.cshtml
importado para que coincidan con los que utiliza el proyecto Server que recibe los archivos.
Pages/_ViewImports.cshtml
(Razor Pages):
@using BlazorHosted.Server
@namespace BlazorHosted.Server.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
Views/_ViewImports.cshtml
(MVC):
@using BlazorHosted.Server
@using BlazorHosted.Server.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
Actualiza el archivo de diseño importado, que es Pages/Shared/_Layout.cshtml
para Razor Pages o Views/Shared/_Layout.cshtml
para MVC.
En primer lugar, elimina el título y la hoja de estilos del proyecto donante, que es RPDonor.styles.css
en el ejemplo siguiente. El marcador de posición {PROJECT NAME}
representa el nombre de la aplicación del proyecto de donantes.
- <title>@ViewData["Title"] - {PROJECT NAME}</title>
- <link rel="stylesheet" href="~/RPDonor.styles.css" asp-append-version="true" />
Incluye los estilos del proyecto Client en el archivo de diseño. En el ejemplo siguiente, el espacio de nombres del proyecto Client es BlazorHosted.Client
. El elemento <title>
se puede actualizar al mismo tiempo.
Coloca las siguientes líneas en el contenido <head>
del archivo de diseño:
<title>@ViewData["Title"] - BlazorHosted</title>
<link href="css/app.css" rel="stylesheet" />
<link rel="stylesheet" href="BlazorHosted.Client.styles.css" asp-append-version="true" />
<component type="typeof(HeadOutlet)" render-mode="WebAssemblyPrerendered" />
El diseño importado contiene dos Home
(página Index
) y vínculos de navegación Privacy
. Para que los vínculos Home
apunten a la aplicación Blazor WebAssembly hospedada, cambia los hipervínculos:
- <a class="navbar-brand" asp-area="" asp-page="/Index">{PROJECT NAME}</a>
+ <a class="navbar-brand" href="/">BlazorHosted</a>
- <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
+ <a class="nav-link text-dark" href="/">Home</a>
En un archivo de diseño de MVC:
- <a class="navbar-brand" asp-area="" asp-controller="Home"
- asp-action="Index">{PROJECT NAME}</a>
+ <a class="navbar-brand" href="/">BlazorHosted</a>
- <a class="nav-link text-dark" asp-area="" asp-controller="Home"
- asp-action="Index">Home</a>
+ <a class="nav-link text-dark" href="/">Home</a>
Actualiza el nombre de la aplicación del elemento <footer>
. El ejemplo siguiente usa el nombre de aplicación BlazorHosted
:
- © {DATE} - {DONOR NAME} - <a asp-area="" asp-page="/Privacy">Privacy</a>
+ © {DATE} - BlazorHosted - <a asp-area="" asp-page="/Privacy">Privacy</a>
En el ejemplo anterior, el marcador de posición {DATE}
representa la fecha de copyright de una aplicación generada a partir de la plantilla de proyecto Razor Pages o MVC.
Para que el vínculo Privacy
dirija a una página de privacy (Razor Pages), agrega una página de privacy al proyecto Server.
Pages/Privacy.cshtml
en el proyecto Server :
@page
@model PrivacyModel
@{
ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>
<p>Use this page to detail your site's privacy policy.</p>
Para una vista de privacy basada en MVC, crea una vista de privacy en el proyecto Server.
View/Home/Privacy.cshtml
en el proyecto Server :
@{
ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>
<p>Use this page to detail your site's privacy policy.</p>
En el controlador Home
de la aplicación MVC, devuelve la vista.
Agrega el código siguiente a Controllers/HomeController.cs
:
public IActionResult Privacy()
{
return View();
}
Si importas archivos desde una aplicación de donantes, asegúrate de actualizar los espacios de nombres de los archivos para que coincidan con el del proyecto Server (por ejemplo, BlazorHosted.Server
).
Importa los recursos estáticos al proyecto Server desde la carpeta wwwroot
del proyecto de donantes:
- Carpeta
wwwroot/css
y su contenido - Carpeta
wwwroot/js
y su contenido - Carpeta
wwwroot/lib
y su contenido
Si el proyecto de donantes se crea a partir de una plantilla de proyecto de ASP.NET Core y los archivos no se han modificado, puedes copiar toda la carpeta wwwroot
de dicho proyecto en el proyecto Server y quitar el archivo de icono favicon.
Advertencia
Evite colocar el recurso estático en las carpetas wwwroot
de Client y Server. Si está presente el mismo archivo en ambas carpetas, se produce una excepción porque el recurso estático de cada carpeta comparte la misma ruta de acceso raíz web. Por lo tanto, hospede un recurso estático en una de las carpetas wwwroot
, no en ambas.
Después de adoptar la configuración anterior, inserte componentes Razor en páginas o vistas del proyecto Server . Usa las instrucciones de las secciones siguientes de este artículo:
- Representación de componentes en una página o vista con la aplicación auxiliar de etiquetas de componentes
- Representación de componentes en una página o vista con un selector de CSS
Representación de componentes en una página o vista con la aplicación auxiliar de etiquetas de componentes
Después de configurar la solución, incluida la configuración adicional, el asistente de etiquetas de componentes admite dos modos de representación para representar un componente de una aplicación Blazor WebAssembly en una página o vista:
En el siguiente ejemplo de Razor Pages, el componente Counter
se representa en una página. Para convertir el componente en interactivo, el script Blazor WebAssembly se incluye en la sección de representación de la página. Si deseas evitar el uso del espacio de nombres completo del componente Counter
con el asistente de etiquetas de componentes ({ASSEMBLY NAME}.Pages.Counter
), agrega una directiva @using
para el espacio de nombres Pages
del proyecto de cliente. En el ejemplo siguiente, el espacio de nombres del proyecto Client es BlazorHosted.Client
.
En el proyecto Server , Pages/RazorPagesCounter1.cshtml
:
@page
@using BlazorHosted.Client.Pages
<component type="typeof(Counter)" render-mode="WebAssemblyPrerendered" />
@section Scripts {
<script src="_framework/blazor.webassembly.js"></script>
}
Ejecuta el proyecto Server . Ve a la página Razor en /razorpagescounter1
. El componente Counter
representado previamente se inserta en la página.
RenderMode configura si el componente:
- Se representa previamente en la página.
- Se representa como HTML estático en la página o si incluye la información necesaria para arrancar una aplicación Blazor desde el agente de usuario.
Para obtener más información sobre el asistente de etiquetas de componentes, como pasar parámetros y configurar RenderMode, consulta Asistente de etiquetas de componente en ASP.NET Core.
Puede ser necesario realizar trabajo adicional en función de los recursos estáticos que usan los componentes y de cómo se organizan las páginas de diseño en una aplicación. Normalmente, los scripts se agregan a la sección de representación de Scripts
de una vista o una página, y las hojas de estilos se agregan al contenido del elemento <head>
del diseño.
Establecer contenido secundario a través de un fragmento de representación
El asistente de etiquetas de componente no admite la recepción de un delegado RenderFragment
para el contenido secundario (por ejemplo, param-ChildContent="..."
). Se recomienda crear un componente Razor (.razor
) que haga referencia al componente que se desea representar con el contenido secundario que se desea pasar y, después, invocar el componente Razor desde la página o vista.
Asegúrate de que los componentes representados previamente de nivel superior no se recortan en la publicación.
Si un asistente de etiquetas de componente hace referencia directamente a un componente de una biblioteca que está sujeta a recortes en la publicación, el componente podría recortarse durante la publicación porque no hay referencias a él desde el código de la aplicación del lado cliente. Como resultado, el componente no se representa previamente y deja un espacio en blanco en la salida. Si esto ocurre, indica al recortador que conserve el componente de biblioteca agregando un atributo DynamicDependency
attribute cualquier clase de la aplicación del lado cliente. Para conservar un componente denominado SomeLibraryComponentToBePreserved
, agrega lo siguiente a cualquier componente:
@using System.Diagnostics.CodeAnalysis
@attribute [DynamicDependency(DynamicallyAccessedMemberTypes.All,
typeof(SomeLibraryComponentToBePreserved))]
Normalmente, el enfoque anterior no es necesario porque, en la mayoría de los casos, la aplicación representa previamente sus componentes (que no se recortan), y estos, a su vez, hacen referencia a componentes de bibliotecas (lo que hace que tampoco se recorten). Usa solo DynamicDependency
explícitamente para representar previamente un componente de biblioteca directamente cuando esté sujeta a recorte.
Representación de componentes en una página o vista con un selector de CSS
Después de configurar la solución, incluida la configuración adicional, agrega los componentes raíz al proyecto Client de una solución de Blazor WebAssembly hospedada en el archivo Program.cs
. En el siguiente ejemplo, el componente Counter
se declara como un componente raíz con un selector de CSS que selecciona el elemento con el objeto id
que coincide con counter-component
. En el ejemplo siguiente, el espacio de nombres del proyecto Client es BlazorHosted.Client
.
En el archivo Program.cs
del proyecto Client , agrega el espacio de nombres de los componentes Razor del proyecto en la parte superior del archivo:
using BlazorHosted.Client.Pages;
Después de establecer el elemento builder
en Program.cs
, agrega el componente Counter
como componente raíz:
builder.RootComponents.Add<Counter>("#counter-component");
En el siguiente ejemplo de Razor Pages, el componente Counter
se representa en una página. Para convertir el componente en interactivo, el script Blazor WebAssembly se incluye en la sección de representación de la página.
En el proyecto Server , Pages/RazorPagesCounter2.cshtml
:
@page
<div id="counter-component">Loading...</div>
@section Scripts {
<script src="_framework/blazor.webassembly.js"></script>
}
Ejecuta el proyecto Server . Ve a la página Razor en /razorpagescounter2
. El componente Counter
representado previamente se inserta en la página.
Puede ser necesario realizar trabajo adicional en función de los recursos estáticos que usan los componentes y de cómo se organizan las páginas de diseño en una aplicación. Normalmente, los scripts se agregan a la sección de representación de Scripts
de una vista o una página, y las hojas de estilos se agregan al contenido del elemento <head>
del diseño.
Nota
En el ejemplo anterior se produce una excepción JSException si una aplicación Blazor WebAssembly se representa previamente y se integra en una Razoraplicación Pages o MVC a la vez con el uso de un selector de CSS. Al navegar a uno de los componentes Razor del proyecto Client o a una página o vista de Server con un componente insertado, se producen una o varias excepciones JSException.
Este comportamiento es normal porque la representación previa y la integración de una aplicación Blazor WebAssembly con componentes de Razor enrutables no son compatibles con el uso de selectores de CSS.
Si has estado trabajando con los ejemplos de las secciones anteriores y solo deseas ver que el selector de CSS funciona en la aplicación de ejemplo, convierte en comentario la especificación del componente raíz App
del archivo Program.cs
del proyecto Client :
- builder.RootComponents.Add<App>("#app");
+ //builder.RootComponents.Add<App>("#app");
Ve a la página o vista con el componente Razor insertado que usa un selector de CSS (por ejemplo, /razorpagescounter2
del ejemplo anterior). La página o vista se carga con el componente insertado y el componente insertado funciona según lo previsto.
Los componentes Razor se pueden integrar en aplicaciones de Razor Pages y MVC. Cuando se representa la página o la vista, los componentes se pueden representar previamente al mismo tiempo.
La representación previa 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 pueden usar para calcular la clasificación de página.
Después de configurar el proyecto, use la guía que aparece en las secciones siguientes en función de los requisitos del proyecto:
- Componentes enrutables: para los componentes que se pueden enrutar directamente desde las solicitudes del usuario. Siga estas instrucciones cuando los visitantes puedan hacer una solicitud HTTP en el explorador para un componente con una directiva
@page
. - Representación de componentes a partir de una página o vista: para los componentes que no se pueden enrutar directamente desde las solicitudes del usuario. Siga estas instrucciones cuando la aplicación inserte componentes en páginas y vistas existentes con el asistente de etiquetas de componente.
Configuración
Siga estas instrucciones para integrar componentes Razor en páginas y vistas de una aplicación Razor Pages o MVC existente.
Importante
El uso de una página de diseño (_Layout.cshtml
) con un asistente de etiquetas de componente para un componente HeadOutlet es necesario para controlar el contenido <head>
, como el título de la página (componente PageTitle) y otros elementos principales (componente HeadContent). Para más información, vea Control del contenido principal en aplicaciones Blazor de ASP.NET Core.
En el archivo de diseño del proyecto:
Agregue la siguiente etiqueta
<base>
y asistente de etiqueta de componente HeadOutlet al elemento<head>
enPages/Shared/_Layout.cshtml
(Razor Pages) oViews/Shared/_Layout.cshtml
(MVC):<base href="~/" /> <component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
El valor
href
(la ruta de acceso base de la aplicación) del ejemplo anterior da por hecho que la aplicación reside en la ruta de acceso URL raíz (/
). Si la aplicación es una subaplicación, sigue las instrucciones de la sección Ruta base de la aplicación del artículo Hospedaje e implementación de ASP.NET Core Blazor.El componente HeadOutlet se usa para representar el contenido principal (
<head>
) para los títulos de página (componente PageTitle) y otros elementos principales (componente HeadContent) establecidos por componentes Razor. Para más información, vea Control del contenido principal en aplicaciones Blazor de ASP.NET Core.Agregue una etiqueta
<script>
para el scriptblazor.server.js
inmediatamente antes de la sección de representaciónScripts
(@await RenderSectionAsync(...)
) en el diseño de la aplicación.Pages/Shared/_Layout.cshtml
(Razor Pages) oViews/Shared/_Layout.cshtml
(MVC):<script src="_framework/blazor.server.js"></script>
El marco agrega el script
blazor.server.js
a la aplicación. No es necesario agregar manualmente un archivo de scriptblazor.server.js
a la aplicación.
Agregue un archivo imports a la carpeta raíz del proyecto con el contenido siguiente. Cambia el marcador de posición
{APP NAMESPACE}
al espacio de nombres del proyecto._Imports.razor
:@using System.Net.Http @using Microsoft.AspNetCore.Authorization @using Microsoft.AspNetCore.Components.Authorization @using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Web @using Microsoft.AspNetCore.Components.Web.Virtualization @using Microsoft.JSInterop @using {APP NAMESPACE}
Registre los servicios Blazor Server en
Program.cs
, donde se registran los servicios:builder.Services.AddServerSideBlazor();
Agrega el punto de conexión del centro Blazor a los puntos de conexión de
Program.cs
donde se asignan las rutas.Coloca la siguiente línea después de la llamada a
MapRazorPages
( Razor Pages) oMapControllerRoute
(MVC):app.MapBlazorHub();
Integra los componentes en cualquier página o vista. Por ejemplo, agrega un componente
Counter
a la carpetaShared
del proyecto.Pages/Shared/Counter.razor
(Razor Pages) oViews/Shared/Counter.razor
(MVC):<h1>Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
Razor Pages:
En la página
Index
del proyecto de una aplicación Razor Pages, agrega el espacio de nombres del componenteCounter
e inserta el componente en la página. Cuando se carga la páginaIndex
, el componenteCounter
se representa previamente en ella. En el ejemplo siguiente, reemplaza el marcador de posición{APP NAMESPACE}
por el espacio de nombres del proyecto.Pages/Index.cshtml
:@page @using {APP NAMESPACE}.Pages.Shared @model IndexModel @{ ViewData["Title"] = "Home page"; } <component type="typeof(Counter)" render-mode="ServerPrerendered" />
MVC:
En la vista
Index
del proyecto de una aplicación MVC, agrega el espacio de nombres del componenteCounter
e inserta el componente en la vista. Cuando se carga la vistaIndex
, el componenteCounter
se representa previamente en ella. En el ejemplo siguiente, reemplaza el marcador de posición{APP NAMESPACE}
por el espacio de nombres del proyecto.Views/Home/Index.cshtml
:@using {APP NAMESPACE}.Views.Shared @{ ViewData["Title"] = "Home Page"; } <component type="typeof(Counter)" render-mode="ServerPrerendered" />
Para obtener más información, consulta la sección Representación de componentes a partir de una página o vista.
Uso de componentes enrutables en una aplicación Razor Pages
Esta sección pertenece a la incorporación de componentes que se pueden enrutar directamente desde las solicitudes del usuario.
Para admitir componentes Razor enrutables en aplicaciones Razor Pages:
Sigue las instrucciones de la sección Configuración.
Agrega un componente
App
a la raíz del proyecto con el contenido siguiente.App.razor
:@using Microsoft.AspNetCore.Components.Routing <Router AppAssembly="typeof(App).Assembly"> <Found Context="routeData"> <RouteView RouteData="routeData" /> </Found> <NotFound> <PageTitle>Not found</PageTitle> <p role="alert">Sorry, there's nothing at this address.</p> </NotFound> </Router>
Agregue una página
_Host
al proyecto con el contenido siguiente.Pages/_Host.cshtml
:@page "/blazor" @namespace {APP NAMESPACE}.Pages.Shared @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers @{ Layout = "_Layout"; } <component type="typeof(App)" render-mode="ServerPrerendered" />
En este escenario, los componentes usan el archivo compartido
_Layout.cshtml
para su diseño.Importante
El uso de una página de diseño (
_Layout.cshtml
) con un asistente de etiquetas de componente para un componente HeadOutlet es necesario para controlar el contenido<head>
, como el título de la página (componente PageTitle) y otros elementos principales (componente HeadContent). Para más información, vea Control del contenido principal en aplicaciones Blazor de ASP.NET Core.RenderMode configura si el componente
App
:- Se representa previamente en la página.
- Se representa como HTML estático en la página o si incluye la información necesaria para arrancar una aplicación Blazor desde el agente de usuario.
Para obtener más información sobre el asistente de etiquetas de componentes, como pasar parámetros y configurar RenderMode, consulta Asistente de etiquetas de componente en ASP.NET Core.
En los puntos de conexión
Program.cs
, agrega una ruta de prioridad baja para la página_Host
como último punto de conexión:app.MapFallbackToPage("/_Host");
Agrega componentes enrutables al proyecto. El ejemplo siguiente es un componente
RoutableCounter
basado en el componenteCounter
de las plantillas de proyecto de Blazor.Pages/RoutableCounter.razor
:@page "/routable-counter" <PageTitle>Routable Counter</PageTitle> <h1>Routable Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
Ejecuta el proyecto y ve al componente
RoutableCounter
enrutable en/routable-counter
.
Para obtener más información sobre los espacios de nombres, consulta la sección Espacios de nombres de componentes.
Uso de componentes enrutables en una aplicación MVC
Esta sección pertenece a la incorporación de componentes que se pueden enrutar directamente desde las solicitudes del usuario.
Para admitir componentes Razor enrutables en aplicaciones MVC, haga lo siguiente:
Sigue las instrucciones de la sección Configuración.
Agrega un componente
App
a la raíz del proyecto con el contenido siguiente.App.razor
:@using Microsoft.AspNetCore.Components.Routing <Router AppAssembly="typeof(App).Assembly"> <Found Context="routeData"> <RouteView RouteData="routeData" /> </Found> <NotFound> <PageTitle>Not found</PageTitle> <p role="alert">Sorry, there's nothing at this address.</p> </NotFound> </Router>
Agregue una vista
_Host
al proyecto con el contenido siguiente.Views/Home/_Host.cshtml
:@namespace {APP NAMESPACE}.Views.Shared @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers @{ Layout = "_Layout"; } <component type="typeof(App)" render-mode="ServerPrerendered" />
Los componentes usan el archivo compartido
_Layout.cshtml
para su diseño.Importante
El uso de una página de diseño (
_Layout.cshtml
) con un asistente de etiquetas de componente para un componente HeadOutlet es necesario para controlar el contenido<head>
, como el título de la página (componente PageTitle) y otros elementos principales (componente HeadContent). Para más información, vea Control del contenido principal en aplicaciones Blazor de ASP.NET Core.RenderMode configura si el componente
App
:- Se representa previamente en la página.
- Se representa como HTML estático en la página o si incluye la información necesaria para arrancar una aplicación Blazor desde el agente de usuario.
Para obtener más información sobre el asistente de etiquetas de componentes, como pasar parámetros y configurar RenderMode, consulta Asistente de etiquetas de componente en ASP.NET Core.
Agrega una acción al controlador Home.
Controllers/HomeController.cs
:public IActionResult Blazor() { return View("_Host"); }
En los puntos de conexión
Program.cs
, agrega una ruta de prioridad baja para la acción del controlador que devuelva la vista_Host
:app.MapFallbackToController("Blazor", "Home");
Crea una carpeta
Pages
en la aplicación MVC y agregue componentes enrutables. El ejemplo siguiente es un componenteRoutableCounter
basado en el componenteCounter
de las plantillas de proyecto de Blazor.Pages/RoutableCounter.razor
:@page "/routable-counter" <PageTitle>Routable Counter</PageTitle> <h1>Routable Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
Ejecuta el proyecto y ve al componente
RoutableCounter
enrutable en/routable-counter
.
Para obtener más información sobre los espacios de nombres, consulta la sección Espacios de nombres de componentes.
Representación de componentes a partir de una página o vista
Esta sección pertenece a la adición de componentes a páginas o vistas, donde los componentes no son enrutables directamente desde las solicitudes del usuario.
Para representar un componente a partir de una página o vista, usa el asistente de etiquetas de componente.
Representación de componentes interactivos con estado
Los componentes interactivos con estado se pueden agregar a una página de Razor o una vista.
Cuando se representa la página o la vista:
- El componente se representa previamente con la página o la vista.
- Se pierde el estado inicial del componente que se usa para la representación previa.
- Cuando se establece la conexión SignalR, se crea un estado del componente.
La siguiente página de Razor representa un componente Counter
:
<h1>Razor Page</h1>
<component type="typeof(Counter)" render-mode="ServerPrerendered"
param-InitialValue="InitialValue" />
@functions {
[BindProperty(SupportsGet=true)]
public int InitialValue { get; set; }
}
Para más información, consulte Asistente de etiquetas de componente en ASP.NET Core.
Importante
El uso de una página de diseño (_Layout.cshtml
) con un asistente de etiquetas de componente para un componente HeadOutlet es necesario para controlar el contenido <head>
, como el título de la página (componente PageTitle) y otros elementos principales (componente HeadContent). Para más información, vea Control del contenido principal en aplicaciones Blazor de ASP.NET Core.
Representación de componentes no interactivos
En la siguiente página de Razor, el componente Counter
se representa de forma estática con un valor inicial que se especifica mediante un formulario. Como el componente se representa de forma estática, no es interactivo:
<h1>Razor Page</h1>
<form>
<input type="number" asp-for="InitialValue" />
<button type="submit">Set initial value</button>
</form>
<component type="typeof(Counter)" render-mode="Static"
param-InitialValue="InitialValue" />
@functions {
[BindProperty(SupportsGet=true)]
public int InitialValue { get; set; }
}
Para más información, consulte Asistente de etiquetas de componente en ASP.NET Core.
Importante
El uso de una página de diseño (_Layout.cshtml
) con un asistente de etiquetas de componente para un componente HeadOutlet es necesario para controlar el contenido <head>
, como el título de la página (componente PageTitle) y otros elementos principales (componente HeadContent). Para más información, vea Control del contenido principal en aplicaciones Blazor de ASP.NET Core.
Espacios de nombres de componentes
Si usas una carpeta personalizada para contener los componentes Razor del proyecto, agrega el espacio de nombres que representa la carpeta a la página o vista, o bien al archivo _ViewImports.cshtml
. En el ejemplo siguiente:
- Los componentes se almacenan en la carpeta
Components
del proyecto. - El marcador de posición
{APP NAMESPACE}
es el espacio de nombres del proyecto.Components
representa el nombre de la carpeta.
@using {APP NAMESPACE}.Components
El archivo _ViewImports.cshtml
se encuentra en la carpeta Pages
de una aplicación Razor Pages o en la carpeta Views
de una aplicación de MVC.
Para obtener más información, consulta Componentes de ASP.NET Core Razor.
Conservación del estado previamente representado
Si no se conserva el estado representado previamente, se pierde el estado usado durante la representación previa, por lo que se debe volver a crear una vez que la aplicación se haya cargado por completo. Si algún estado se configura de forma asincrónica, puede que la interfaz de usuario representada previamente parpadee mientras se sustituye por marcadores de posición temporales y se vuelve a representar.
Para solucionar estos problemas, Blazor admite el estado persistente en una página representada previamente mediante el Asistente para la conservación de etiquetas de estado de componente. Agregue la etiqueta de asistente de etiquetas <persist-component-state />
a la etiqueta de cierre </body>
.
Pages/_Layout.cshtml
:
<body>
...
<persist-component-state />
</body>
En la aplicación, decide qué estado quieres conservar mediante el servicio PersistentComponentState. PersistentComponentState.RegisterOnPersisting
registra una devolución de llamada para conservar el estado del componente antes de que se pause la aplicación. El estado se recupera cuando se reanuda la aplicación.
El ejemplo siguiente es una versión actualizada del componente FetchData
en una aplicación de Blazor WebAssembly hospedada basada en la plantilla de proyecto Blazor. El componente WeatherForecastPreserveState
conserva el estado de previsión meteorológica durante la representación previa y, después, recupera el estado para inicializar el componente. El Asistente para la conservación de etiquetas de estado de componente conserva el estado del componente después de todas las invocaciones de componentes.
Pages/WeatherForecastPreserveState.razor
:
@page "/weather-forecast-preserve-state"
@implements IDisposable
@using BlazorSample.Shared
@inject IWeatherForecastService WeatherForecastService
@inject PersistentComponentState ApplicationState
<PageTitle>Weather Forecast</PageTitle>
<h1>Weather forecast</h1>
<p>This component demonstrates fetching data from the server.</p>
@if (forecasts == null)
{
<p><em>Loading...</em></p>
}
else
{
<table class="table">
<thead>
<tr>
<th>Date</th>
<th>Temp. (C)</th>
<th>Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
@foreach (var forecast in forecasts)
{
<tr>
<td>@forecast.Date.ToShortDateString()</td>
<td>@forecast.TemperatureC</td>
<td>@forecast.TemperatureF</td>
<td>@forecast.Summary</td>
</tr>
}
</tbody>
</table>
}
@code {
private WeatherForecast[] forecasts = Array.Empty<WeatherForecast>();
private PersistingComponentStateSubscription persistingSubscription;
protected override async Task OnInitializedAsync()
{
persistingSubscription =
ApplicationState.RegisterOnPersisting(PersistForecasts);
if (!ApplicationState.TryTakeFromJson<WeatherForecast[]>(
"fetchdata", out var restored))
{
forecasts =
await WeatherForecastService.GetForecastAsync(DateTime.Now);
}
else
{
forecasts = restored!;
}
}
private Task PersistForecasts()
{
ApplicationState.PersistAsJson("fetchdata", forecasts);
return Task.CompletedTask;
}
void IDisposable.Dispose()
{
persistingSubscription.Dispose();
}
}
Al inicializar componentes con el mismo estado que se usa durante la representación previa, los pasos de inicialización costosos solo se ejecutan una vez. La interfaz de usuario representada también coincide con la que se ha representado previamente, por lo que no se produce ningún parpadeo en el explorador.
El estado preenderado persistente se transfiere al cliente, donde se usa para restaurar el estado del componente. ASP.NET Protección de datos principales garantiza que los datos se transfieren de forma segura en Blazor Server las aplicaciones. Para la representación previa en una aplicación hospedada Blazor WebAssembly , los datos se exponen al explorador y no deben contener información confidencial y privada.
Recursos de Blazor WebAssembly adicionales
- Administración de estados: control de la representación previa
- Compatibilidad con la representación previa con la carga diferida de ensamblados
- Temas del ciclo de vida de los componentes Razor relacionados con la representación previa
- Inicialización de componentes (
OnInitialized{Async}
) - Después de representar el componente (
OnAfterRender{Async}
) - Reconexión con estado después de la representación previa: aunque el contenido de la sección se centra en Blazor Server y en la reconexión de SignalR con estado, el escenario de representación previa de las aplicaciones Blazor WebAssembly hospedadas (WebAssemblyPrerendered) conlleva condiciones y enfoques similares para evitar ejecutar dos veces el código del desarrollador. Para preservar el estado durante la ejecución del código de inicialización mientras se realiza la renderización previa, consulta la sección Persistir el estado de la renderización previa de este artículo.
- Representación previa con interoperabilidad de JavaScript
- Inicialización de componentes (
- Aspectos de autenticación y autorización relacionados con la representación previa
- Hospedaje e implementación: Blazor WebAssembly
Tamaño de estado antes de la representación y límite de tamaño del mensaje SignalR
Un tamaño grande de estado anterior a la representación puede superar el límite de tamaño del mensaje de circuito SignalR, lo que da como resultado lo siguiente:
- El circuito SignalR no se puede inicializar con un error en el cliente: Circuit host not initialized.
- La interfaz de usuario de reconexión del cliente aparece cuando se produce un error en el circuito. No es posible la recuperación.
Para resolver el problema, usa uno de los enfoques siguientes:
- Reduce la cantidad de datos que se están colocando en el estado anterior a la representación.
- Aumenta el límite de tamaño del mensajeSignalR. ADVERTENCIA: Aumentar el límite puede aumentar el riesgo de ataques por denegación de servicio (DoS).
Recursos de Blazor Server adicionales
- Administración de estados: control de la representación previa
- Temas del ciclo de vida de los componentes Razor relacionados con la representación previa
- Autenticación y autorización: aspectos generales
- Control de errores: representación previa de
- Hospedaje e implementación: Blazor Server
- Mitigación de amenazas: scripting entre sitios (XSS)
Los componentes Razor se pueden integrar en aplicaciones Razor Pages y MVC de una soluciónBlazor WebAssembly hospedada. Cuando se representa la página o la vista, los componentes se pueden representar previamente al mismo tiempo.
La representación previa 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 pueden usar para calcular la clasificación de página.
Configuración de la solución
Configuración de la representación previa
Para configurar la representación previa de una aplicación Blazor WebAssembly hospedada:
Hospede la aplicación Blazor WebAssembly en una aplicación ASP.NET Core. Se puede agregar una aplicación Blazor WebAssembly independiente a una solución de ASP.NET Core, o bien se puede usar una aplicación Blazor WebAssembly hospedada creada a partir de la plantilla de proyecto de Blazor WebAssembly con la opción hospedada:
- Visual Studio: activa la casilla ASP.NET Core hospedado del cuadro de diálogo Información adicional al crear la aplicación Blazor WebAssembly. En los ejemplos de este artículo, la solución se llama
BlazorHosted
. - Shell de comandos de la CLI de Visual Studio Code/:NET:
dotnet new blazorwasm -ho
(use la opción-ho|--hosted
). Usa la opción-o|--output {LOCATION}
para crear una carpeta para la solución y establecer los espacios de nombres del proyecto de la solución. En los ejemplos de este artículo, la solución se llamaBlazorHosted
(dotnet new blazorwasm -ho -o BlazorHosted
).
En los ejemplos de este artículo, el espacio de nombres del proyecto de cliente es
BlazorHosted.Client
y el espacio de nombres del proyecto de servidor esBlazorHosted.Server
.- Visual Studio: activa la casilla ASP.NET Core hospedado del cuadro de diálogo Información adicional al crear la aplicación Blazor WebAssembly. En los ejemplos de este artículo, la solución se llama
Elimina el archivo
wwwroot/index.html
del proyecto Client de Blazor WebAssembly.En el proyecto Client, elimina la línea siguiente en
Program.cs
:- builder.RootComponents.Add<App>("#app");
Agrega un archivo
Pages/_Host.cshtml
a la carpetaPages
del proyecto Server . Puedes obtener un archivo_Host.cshtml
de un proyecto creado a partir de la plantilla de Blazor Server con el comandodotnet new blazorserver -o BlazorServer
de un shell de comandos (la opción-o BlazorServer
crea una carpeta para el proyecto). Después de colocar el archivoPages/_Host.cshtml
en el proyecto Server de la solución Blazor WebAssembly hospedada, realiza en él los siguientes cambios:Proporciona una directiva
@using
para el proyecto Client (por ejemplo,@using BlazorHosted.Client
).Actualiza los vínculos de la hoja de estilos para que apunten a las hojas de estilos del proyecto de WebAssembly. En el ejemplo siguiente, el espacio de nombres del proyecto de cliente es
BlazorHosted.Client
:- <link href="css/site.css" rel="stylesheet" /> - <link href="_content/BlazorServer/_framework/scoped.styles.css" rel="stylesheet" /> + <link href="css/app.css" rel="stylesheet" /> + <link href="BlazorHosted.Client.styles.css" rel="stylesheet" />
Nota
Deja como está el elemento
<link>
que solicita la hoja de estilos de arranquecss/bootstrap/bootstrap.min.css
.Actualiza el objeto
render-mode
del asistente de etiquetas de componentes para representar previamente el componenteApp
raíz con WebAssemblyPrerendered:- <component type="typeof(App)" render-mode="ServerPrerendered" /> + <component type="typeof(App)" render-mode="WebAssemblyPrerendered" />
Actualiza el origen del script de Blazor para usar el script de Blazor WebAssembly del lado cliente:
- <script src="_framework/blazor.server.js"></script> + <script src="_framework/blazor.webassembly.js"></script>
En el objeto
Startup.Configure
del proyecto Server , cambia la reserva del archivoindex.html
a la página_Host.cshtml
.Startup.cs
:- endpoints.MapFallbackToFile("index.html"); + endpoints.MapFallbackToPage("/_Host");
Si los proyectos Client y Server usan uno o varios servicios comunes durante la representación previa, factoriza los registros de servicio en un método al que se puede llamar desde ambos proyectos. Para obtener más información, consulta Inserción de dependencias de ASP.NET Core Blazor.
Ejecuta el proyecto Server . La aplicación Blazor WebAssembly hospedada se representa previamente en el proyecto Server para los clientes.
Configuración para insertar componentes Razor en páginas y vistas
En las secciones y ejemplos siguientes de este artículo para insertar componentes Razor de la aplicación cliente Blazor WebAssembly en páginas y vistas de la aplicación de servidor se necesita configuración adicional.
Usa un archivo de diseño de Razor Pages o MVC en el proyecto Server. El proyecto Server debe tener los siguientes archivos y carpetas.
Razor Pages:
Pages/Shared/_Layout.cshtml
Pages/_ViewImports.cshtml
Pages/_ViewStart.cshtml
MVC:
Views/Shared/_Layout.cshtml
Views/_ViewImports.cshtml
Views/_ViewStart.cshtml
Obtén los archivos anteriores de una aplicación creada a partir de la plantilla de proyecto de Razor Pages o MVC. Para obtener más información, consulta Tutorial: Introducción a las páginas de Razor en ASP.NET Core o Introducción a ASP.NET Core MVC.
Actualiza los espacios de nombres del archivo _ViewImports.cshtml
importado para que coincidan con los que utiliza el proyecto Server que recibe los archivos.
Actualiza el archivo de diseño importado (_Layout.cshtml
) para incluir los estilos del proyecto Client . En el ejemplo siguiente, el espacio de nombres del proyecto Client es BlazorHosted.Client
. El elemento <title>
se puede actualizar al mismo tiempo.
Pages/Shared/_Layout.cshtml
(Razor Pages) o Views/Shared/_Layout.cshtml
(MVC):
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <title>@ViewData["Title"] - DonorProject</title>
+ <title>@ViewData["Title"] - BlazorHosted</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" />
+ <link href="css/app.css" rel="stylesheet" />
+ <link href="BlazorHosted.Client.styles.css" rel="stylesheet" />
</head>
El diseño importado contiene los vínculos de navegación Home
y Privacy
. Para que el vínculo Home
apunte a la aplicación Blazor WebAssembly hospedada, cambia el hipervínculo:
- <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
+ <a class="nav-link text-dark" href="/">Home</a>
En un archivo de diseño de MVC:
- <a class="nav-link text-dark" asp-area="" asp-controller="Home"
- asp-action="Index">Home</a>
+ <a class="nav-link text-dark" href="/">Home</a>
Para que el vínculo Privacy
dirija a una página privacy, agrega una página privacy al proyecto Server.
Pages/Privacy.cshtml
en el proyecto Server :
@page
@model BlazorHosted.Server.Pages.PrivacyModel
@{
}
<h1>Privacy Policy</h1>
Si se prefiere una vista privacy basada en MVC, crea una vista privacy en el proyecto Server.
View/Home/Privacy.cshtml
:
@{
ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>
En el controlador Home
, devuelva la vista.
Controllers/HomeController.cs
:
public IActionResult Privacy()
{
return View();
}
Importa los recursos estáticos al proyecto Server desde la carpeta wwwroot
del proyecto de donantes:
- Carpeta
wwwroot/css
y su contenido - Carpeta
wwwroot/js
y su contenido - Carpeta
wwwroot/lib
y su contenido
Si el proyecto de donantes se crea a partir de una plantilla de proyecto de ASP.NET Core y los archivos no se han modificado, puedes copiar toda la carpeta wwwroot
de dicho proyecto en el proyecto Server y quitar el archivo de icono favicon.
Advertencia
Evite colocar el recurso estático en las carpetas wwwroot
de Client y Server. Si está presente el mismo archivo en ambas carpetas, se produce una excepción porque el recurso estático de cada carpeta comparte la misma ruta de acceso raíz web. Por lo tanto, hospede un recurso estático en una de las carpetas wwwroot
, no en ambas.
Representación de componentes en una página o vista con la aplicación auxiliar de etiquetas de componentes
Después de configurar la solución, incluida la configuración adicional, el asistente de etiquetas de componentes admite dos modos de representación para representar un componente de una aplicación Blazor WebAssembly en una página o vista:
En el siguiente ejemplo de Razor Pages, el componente Counter
se representa en una página. Para convertir el componente en interactivo, el script Blazor WebAssembly se incluye en la sección de representación de la página. Si deseas evitar el uso del espacio de nombres completo del componente Counter
con el asistente de etiquetas de componentes ({ASSEMBLY NAME}.Pages.Counter
), agrega una directiva @using
para el espacio de nombres Pages
del proyecto de cliente. En el ejemplo siguiente, el espacio de nombres del proyecto Client es BlazorHosted.Client
.
En el proyecto Server , Pages/RazorPagesCounter1.cshtml
:
@page
@using BlazorHosted.Client.Pages
<component type="typeof(Counter)" render-mode="WebAssemblyPrerendered" />
@section Scripts {
<script src="_framework/blazor.webassembly.js"></script>
}
Ejecuta el proyecto Server . Ve a la página Razor en /razorpagescounter1
. El componente Counter
representado previamente se inserta en la página.
RenderMode configura si el componente:
- Se representa previamente en la página.
- Se representa como HTML estático en la página o si incluye la información necesaria para arrancar una aplicación Blazor desde el agente de usuario.
Para obtener más información sobre el asistente de etiquetas de componentes, como pasar parámetros y configurar RenderMode, consulta Asistente de etiquetas de componente en ASP.NET Core.
Puede ser necesario realizar trabajo adicional en función de los recursos estáticos que usan los componentes y de cómo se organizan las páginas de diseño en una aplicación. Normalmente, los scripts se agregan a la sección de representación de Scripts
de una vista o una página, y las hojas de estilos se agregan al contenido del elemento <head>
del diseño.
Representación de componentes en una página o vista con un selector de CSS
Después de configurar la solución, incluida la configuración adicional, agregue los componentes raíz al proyecto Client de una solución de Blazor WebAssembly hospedada en Program.cs
. En el siguiente ejemplo, el componente Counter
se declara como un componente raíz con un selector de CSS que selecciona el elemento con el objeto id
que coincide con counter-component
. En el ejemplo siguiente, el espacio de nombres del proyecto Client es BlazorHosted.Client
.
En el archivo Program.cs
del proyecto Client , agregue el espacio de nombres de los componentes Razor del proyecto en la parte superior del archivo:
using BlazorHosted.Client.Pages;
Después de establecer el elemento builder
en Program.cs
, agregue el componente Counter
como componente raíz:
builder.RootComponents.Add<Counter>("#counter-component");
En el siguiente ejemplo de Razor Pages, el componente Counter
se representa en una página. Para convertir el componente en interactivo, el script Blazor WebAssembly se incluye en la sección de representación de la página.
En el proyecto Server , Pages/RazorPagesCounter2.cshtml
:
@page
<div id="counter-component">Loading...</div>
@section Scripts {
<script src="_framework/blazor.webassembly.js"></script>
}
Ejecuta el proyecto Server . Ve a la página Razor en /razorpagescounter2
. El componente Counter
representado previamente se inserta en la página.
Puede ser necesario realizar trabajo adicional en función de los recursos estáticos que usan los componentes y de cómo se organizan las páginas de diseño en una aplicación. Normalmente, los scripts se agregan a la sección de representación de Scripts
de una vista o una página, y las hojas de estilos se agregan al contenido del elemento <head>
del diseño.
Nota
En el ejemplo anterior se produce una excepción JSException si una aplicación Blazor WebAssembly se representa previamente y se integra en una aplicación Razor Pages o MVC a la vez con un selector de CSS. Al desplazarse a uno de los componentes Razor del proyecto Client se produce la siguiente excepción:
Microsoft.JSInterop.JSException: Could not find any element matching selector '#counter-component' (No se ha podido encontrar ningún elemento que coincida con el selector "#counter-component").
Este comportamiento es normal porque la representación previa y la integración de una aplicación Blazor WebAssembly con componentes de Razor enrutables no son compatibles con el uso de selectores de CSS.
Los componentes Razor se pueden integrar en aplicaciones de Razor Pages y MVC. Cuando se representa la página o la vista, los componentes se pueden representar previamente al mismo tiempo.
La representación previa 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 pueden usar para calcular la clasificación de página.
Después de configurar el proyecto, use la guía que aparece en las secciones siguientes en función de los requisitos del proyecto:
- Componentes enrutables: para los componentes que se pueden enrutar directamente desde las solicitudes del usuario. Siga estas instrucciones cuando los visitantes puedan hacer una solicitud HTTP en el explorador para un componente con una directiva
@page
. - Representación de componentes a partir de una página o vista: para los componentes que no se pueden enrutar directamente desde las solicitudes del usuario. Siga estas instrucciones cuando la aplicación inserte componentes en páginas y vistas existentes con el asistente de etiquetas de componente.
Configuración
Una aplicación Razor Pages o MVC existente puede integrar componentes Razor en páginas y vistas:
En el archivo de diseño del proyecto:
Agregue la siguiente etiqueta
<base>
al elemento<head>
enPages/Shared/_Layout.cshtml
(Razor Pages) oViews/Shared/_Layout.cshtml
(MVC):<base href="~/" />
El valor
href
(la ruta de acceso base de la aplicación) del ejemplo anterior da por hecho que la aplicación reside en la ruta de acceso URL raíz (/
). Si la aplicación es una subaplicación, siga las instrucciones de la sección Ruta base de la aplicación del artículo Hospedaje e implementación de ASP.NET Core Blazor.Agregue una etiqueta
<script>
para el scriptblazor.server.js
inmediatamente antes de la sección de representaciónScripts
.Pages/Shared/_Layout.cshtml
(Razor Pages) oViews/Shared/_Layout.cshtml
(MVC):... <script src="_framework/blazor.server.js"></script> @await RenderSectionAsync("Scripts", required: false) </body>
El marco agrega el script
blazor.server.js
a la aplicación. No es necesario agregar manualmente un archivo de scriptblazor.server.js
a la aplicación.
Agregue un archivo imports a la carpeta raíz del proyecto con el contenido siguiente. Cambia el marcador de posición
{APP NAMESPACE}
al espacio de nombres del proyecto._Imports.razor
:@using System.Net.Http @using Microsoft.AspNetCore.Authorization @using Microsoft.AspNetCore.Components.Authorization @using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Web @using Microsoft.JSInterop @using {APP NAMESPACE}
Registre el servicio Blazor Server en
Startup.ConfigureServices
.En
Startup.cs
:services.AddServerSideBlazor();
Agregue el punto de conexión Blazor Hub a los puntos de conexión (
app.UseEndpoints
) deStartup.Configure
.Startup.cs
:endpoints.MapBlazorHub();
Integre los componentes en cualquier página o vista. Por ejemplo, agrega un componente
Counter
a la carpetaShared
del proyecto.Pages/Shared/Counter.razor
(Razor Pages) oViews/Shared/Counter.razor
(MVC):<h1>Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
Razor Pages:
En la página
Index
del proyecto de una aplicación Razor Pages, agrega el espacio de nombres del componenteCounter
e inserta el componente en la página. Cuando se carga la páginaIndex
, el componenteCounter
se representa previamente en ella. En el ejemplo siguiente, reemplaza el marcador de posición{APP NAMESPACE}
por el espacio de nombres del proyecto.Pages/Index.cshtml
:@page @using {APP NAMESPACE}.Pages.Shared @model IndexModel @{ ViewData["Title"] = "Home page"; } <div> <component type="typeof(Counter)" render-mode="ServerPrerendered" /> </div>
En el ejemplo anterior, reemplace el marcador de posición
{APP NAMESPACE}
por el espacio de nombres de la aplicación.MVC:
En la vista
Index
del proyecto de una aplicación MVC, agrega el espacio de nombres del componenteCounter
e inserta el componente en la vista. Cuando se carga la vistaIndex
, el componenteCounter
se representa previamente en ella. En el ejemplo siguiente, reemplaza el marcador de posición{APP NAMESPACE}
por el espacio de nombres del proyecto.Views/Home/Index.cshtml
:@using {APP NAMESPACE}.Views.Shared @{ ViewData["Title"] = "Home Page"; } <div> <component type="typeof(Counter)" render-mode="ServerPrerendered" /> </div>
Para obtener más información, consulta la sección Representación de componentes a partir de una página o vista.
Uso de componentes enrutables en una aplicación Razor Pages
Esta sección pertenece a la incorporación de componentes que se pueden enrutar directamente desde las solicitudes del usuario.
Para admitir componentes Razor enrutables en aplicaciones Razor Pages:
Sigue las instrucciones de la sección Configuración.
Agrega un componente
App
a la raíz del proyecto con el contenido siguiente.App.razor
:@using Microsoft.AspNetCore.Components.Routing <Router AppAssembly="typeof(Program).Assembly"> <Found Context="routeData"> <RouteView RouteData="routeData" /> </Found> <NotFound> <h1>Page not found</h1> <p>Sorry, but there's nothing here!</p> </NotFound> </Router>
Nota
Con la publicación de ASP.NET Core 5.0.1 y para las versiones 5.x adicionales, el componente
Router
incluye el parámetroPreferExactMatches
establecido en@true
. Para más información, vea Migración de ASP.NET Core 3.1 a 5.0.Agregue una página
_Host
al proyecto con el contenido siguiente.Pages/_Host.cshtml
:@page "/blazor" @{ Layout = "_Layout"; } <app> <component type="typeof(App)" render-mode="ServerPrerendered" /> </app>
Los componentes usan el archivo compartido
_Layout.cshtml
para su diseño.RenderMode configura si el componente
App
:- Se representa previamente en la página.
- Se representa como HTML estático en la página o si incluye la información necesaria para arrancar una aplicación Blazor desde el agente de usuario.
Para obtener más información sobre el asistente de etiquetas de componentes, como pasar parámetros y configurar RenderMode, vea Asistente de etiquetas de componente en ASP.NET Core.
En los puntos de conexión
Startup.Configure
deStartup.cs
, agregue una ruta de prioridad baja para la página_Host
como último punto de conexión:endpoints.MapFallbackToPage("/_Host");
En el ejemplo siguiente se muestra la línea agregada en la configuración del punto de conexión de una aplicación típica:
app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); endpoints.MapBlazorHub(); endpoints.MapFallbackToPage("/_Host"); });
Agregue componentes enrutables al proyecto.
Pages/RoutableCounter.razor
:@page "/routable-counter" <h1>Routable Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
Ejecuta el proyecto y ve al componente
RoutableCounter
enrutable en/routable-counter
.
Para obtener más información sobre los espacios de nombres, consulta la sección Espacios de nombres de componentes.
Uso de componentes enrutables en una aplicación MVC
Esta sección pertenece a la incorporación de componentes que se pueden enrutar directamente desde las solicitudes del usuario.
Para admitir componentes Razor enrutables en aplicaciones MVC, haga lo siguiente:
Sigue las instrucciones de la sección Configuración.
Agrega un componente
App
a la raíz del proyecto con el contenido siguiente.App.razor
:@using Microsoft.AspNetCore.Components.Routing <Router AppAssembly="typeof(Program).Assembly"> <Found Context="routeData"> <RouteView RouteData="routeData" /> </Found> <NotFound> <h1>Page not found</h1> <p>Sorry, but there's nothing here!</p> </NotFound> </Router>
Nota
Con la publicación de ASP.NET Core 5.0.1 y para las versiones 5.x adicionales, el componente
Router
incluye el parámetroPreferExactMatches
establecido en@true
. Para más información, vea Migración de ASP.NET Core 3.1 a 5.0.Agregue una vista
_Host
al proyecto con el contenido siguiente.Views/Home/_Host.cshtml
:@{ Layout = "_Layout"; } <app> <component type="typeof(App)" render-mode="ServerPrerendered" /> </app>
Los componentes usan el archivo compartido
_Layout.cshtml
para su diseño.RenderMode configura si el componente
App
:- Se representa previamente en la página.
- Se representa como HTML estático en la página o si incluye la información necesaria para arrancar una aplicación Blazor desde el agente de usuario.
Para obtener más información sobre el asistente de etiquetas de componentes, como pasar parámetros y configurar RenderMode, consulta Asistente de etiquetas de componente en ASP.NET Core.
Agrega una acción al controlador Home.
Controllers/HomeController.cs
:public IActionResult Blazor() { return View("_Host"); }
En los puntos de conexión
Startup.Configure
deStartup.cs
, agregue una ruta de prioridad baja para la acción del controlador que devuelva la vista_Host
:endpoints.MapFallbackToController("Blazor", "Home");
En el ejemplo siguiente se muestra la línea agregada en la configuración del punto de conexión de una aplicación típica:
app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); endpoints.MapBlazorHub(); endpoints.MapFallbackToController("Blazor", "Home"); });
Agregue componentes enrutables al proyecto.
Pages/RoutableCounter.razor
:@page "/routable-counter" <h1>Routable Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
Ejecuta el proyecto y ve al componente
RoutableCounter
enrutable en/routable-counter
.
Para obtener más información sobre los espacios de nombres, consulta la sección Espacios de nombres de componentes.
Representación de componentes a partir de una página o vista
Esta sección pertenece a la adición de componentes a páginas o vistas, donde los componentes no son enrutables directamente desde las solicitudes del usuario.
Para representar un componente a partir de una página o vista, usa el asistente de etiquetas de componente.
Representación de componentes interactivos con estado
Los componentes interactivos con estado se pueden agregar a una página de Razor o una vista.
Cuando se representa la página o la vista:
- El componente se representa previamente con la página o la vista.
- Se pierde el estado inicial del componente que se usa para la representación previa.
- Cuando se establece la conexión SignalR, se crea un estado del componente.
La siguiente página de Razor representa un componente Counter
:
<h1>My Razor Page</h1>
<component type="typeof(Counter)" render-mode="ServerPrerendered"
param-InitialValue="InitialValue" />
@functions {
[BindProperty(SupportsGet=true)]
public int InitialValue { get; set; }
}
Para obtener más información, consulta Asistente de etiquetas de componente en ASP.NET Core.
Representación de componentes no interactivos
En la siguiente página de Razor, el componente Counter
se representa de forma estática con un valor inicial que se especifica mediante un formulario. Como el componente se representa de forma estática, no es interactivo:
<h1>My Razor Page</h1>
<form>
<input type="number" asp-for="InitialValue" />
<button type="submit">Set initial value</button>
</form>
<component type="typeof(Counter)" render-mode="Static"
param-InitialValue="InitialValue" />
@functions {
[BindProperty(SupportsGet=true)]
public int InitialValue { get; set; }
}
Para obtener más información, consulta Asistente de etiquetas de componente en ASP.NET Core.
Espacios de nombres de componentes
Si usas una carpeta personalizada para contener los componentes Razor del proyecto, agrega el espacio de nombres que representa la carpeta a la página o vista, o bien al archivo _ViewImports.cshtml
. En el ejemplo siguiente:
- Los componentes se almacenan en la carpeta
Components
del proyecto. - El marcador de posición
{APP NAMESPACE}
es el espacio de nombres del proyecto.Components
representa el nombre de la carpeta.
@using {APP NAMESPACE}.Components
El archivo _ViewImports.cshtml
se encuentra en la carpeta Pages
de una aplicación Razor Pages o en la carpeta Views
de una aplicación de MVC.
Para más información, vea Componentes Razor de ASP.NET Core.
Recursos de Blazor WebAssembly adicionales
- Administración de estados: control de la representación previa
- Compatibilidad con la representación previa con la carga diferida de ensamblados
- Temas del ciclo de vida de los componentes Razor relacionados con la representación previa
- Inicialización de componentes (
OnInitialized{Async}
) - Después de representar el componente (
OnAfterRender{Async}
) - Reconexión con estado después de la representación previa: aunque el contenido de la sección se centra en Blazor Server y en la reconexión de SignalR con estado, el escenario de representación previa de las aplicaciones Blazor WebAssembly hospedadas (WebAssemblyPrerendered) conlleva condiciones y enfoques similares para evitar ejecutar dos veces el código del desarrollador. Para preservar el estado durante la ejecución del código de inicialización mientras se realiza la renderización previa, consulta la sección Persistir el estado de la renderización previa de este artículo.
- Representación previa con interoperabilidad de JavaScript
- Inicialización de componentes (
- Aspectos de autenticación y autorización relacionados con la representación previa
- Hospedaje e implementación: Blazor WebAssembly
Tamaño de estado antes de la representación y límite de tamaño del mensaje SignalR
Un tamaño grande de estado anterior a la representación puede superar el límite de tamaño del mensaje de circuito SignalR, lo que da como resultado lo siguiente:
- El circuito SignalR no se puede inicializar con un error en el cliente: Circuit host not initialized.
- La interfaz de usuario de reconexión del cliente aparece cuando se produce un error en el circuito. No es posible la recuperación.
Para resolver el problema, usa uno de los enfoques siguientes:
- Reduce la cantidad de datos que se están colocando en el estado anterior a la representación.
- Aumenta el límite de tamaño del mensajeSignalR. ADVERTENCIA: Aumentar el límite puede aumentar el riesgo de ataques por denegación de servicio (DoS).
Recursos de Blazor Server adicionales
- Administración de estados: control de la representación previa
- Temas del ciclo de vida de los componentes Razor relacionados con la representación previa
- Autenticación y autorización: aspectos generales
- Control de errores: representación previa de
- Hospedaje e implementación: Blazor Server
- Mitigación de amenazas: scripting entre sitios (XSS)
La integración de componentes Razor en aplicaciones Razor Pages y MVC de una soluciónBlazor WebAssembly hospedada se admite en ASP.NET Core en .NET 5 o versiones posteriores. Seleccione una versión .NET 5 o posterior de este artículo.
Los componentes Razor se pueden integrar en aplicaciones de Razor Pages y MVC. Cuando se representa la página o la vista, los componentes se pueden representar previamente al mismo tiempo.
La representación previa 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 pueden usar para calcular la clasificación de página.
Después de configurar el proyecto, use la guía que aparece en las secciones siguientes en función de los requisitos del proyecto:
- Componentes enrutables: para los componentes que se pueden enrutar directamente desde las solicitudes del usuario. Siga estas instrucciones cuando los visitantes puedan hacer una solicitud HTTP en el explorador para un componente con una directiva
@page
. - Representación de componentes a partir de una página o vista: para los componentes que no se pueden enrutar directamente desde las solicitudes del usuario. Siga estas instrucciones cuando la aplicación inserte componentes en páginas y vistas existentes con el asistente de etiquetas de componente.
Configuración
Una aplicación Razor Pages o MVC existente puede integrar componentes Razor en páginas y vistas:
En el archivo de diseño del proyecto:
Agregue la siguiente etiqueta
<base>
al elemento<head>
enPages/Shared/_Layout.cshtml
(Razor Pages) oViews/Shared/_Layout.cshtml
(MVC):+ <base href="~/" />
El valor
href
(la ruta de acceso base de la aplicación) del ejemplo anterior da por hecho que la aplicación reside en la ruta de acceso URL raíz (/
). Si la aplicación es una subaplicación, siga las instrucciones de la sección Ruta base de la aplicación del artículo Hospedaje e implementación de ASP.NET Core Blazor.Agregue una etiqueta
<script>
para el scriptblazor.server.js
inmediatamente antes de la sección de representaciónScripts
.Pages/Shared/_Layout.cshtml
(Razor Pages) oViews/Shared/_Layout.cshtml
(MVC):... <script src="_framework/blazor.server.js"></script> @await RenderSectionAsync("Scripts", required: false) </body>
El marco agrega el script
blazor.server.js
a la aplicación. No es necesario agregar manualmente un archivo de scriptblazor.server.js
a la aplicación.
Agregue un archivo imports a la carpeta raíz del proyecto con el contenido siguiente. Cambia el marcador de posición
{APP NAMESPACE}
al espacio de nombres del proyecto._Imports.razor
:@using System.Net.Http @using Microsoft.AspNetCore.Authorization @using Microsoft.AspNetCore.Components.Authorization @using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Web @using Microsoft.JSInterop @using {APP NAMESPACE}
Registre el servicio Blazor Server en
Startup.ConfigureServices
.Startup.cs
:services.AddServerSideBlazor();
Agregue el punto de conexión Blazor Hub a los puntos de conexión (
app.UseEndpoints
) deStartup.Configure
.Startup.cs
:endpoints.MapBlazorHub();
Integre los componentes en cualquier página o vista. Por ejemplo, agrega un componente
Counter
a la carpetaShared
del proyecto.Pages/Shared/Counter.razor
(Razor Pages) oViews/Shared/Counter.razor
(MVC):<h1>Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
Razor Pages:
En la página
Index
del proyecto de una aplicación Razor Pages, agrega el espacio de nombres del componenteCounter
e inserta el componente en la página. Cuando se carga la páginaIndex
, el componenteCounter
se representa previamente en ella. En el ejemplo siguiente, reemplaza el marcador de posición{APP NAMESPACE}
por el espacio de nombres del proyecto.Pages/Index.cshtml
:@page @using {APP NAMESPACE}.Pages.Shared @model IndexModel @{ ViewData["Title"] = "Home page"; } <div> <component type="typeof(Counter)" render-mode="ServerPrerendered" /> </div>
En el ejemplo anterior, reemplace el marcador de posición
{APP NAMESPACE}
por el espacio de nombres de la aplicación.MVC:
En la vista
Index
del proyecto de una aplicación MVC, agrega el espacio de nombres del componenteCounter
e inserta el componente en la vista. Cuando se carga la vistaIndex
, el componenteCounter
se representa previamente en ella. En el ejemplo siguiente, reemplaza el marcador de posición{APP NAMESPACE}
por el espacio de nombres del proyecto.Views/Home/Index.cshtml
:@using {APP NAMESPACE}.Views.Shared @{ ViewData["Title"] = "Home Page"; } <div> <component type="typeof(Counter)" render-mode="ServerPrerendered" /> </div>
Para obtener más información, consulta la sección Representación de componentes a partir de una página o vista.
Uso de componentes enrutables en una aplicación Razor Pages
Esta sección pertenece a la incorporación de componentes que se pueden enrutar directamente desde las solicitudes del usuario.
Para admitir componentes Razor enrutables en aplicaciones Razor Pages:
Sigue las instrucciones de la sección Configuración.
Agrega un componente
App
a la raíz del proyecto con el contenido siguiente.App.razor
:@using Microsoft.AspNetCore.Components.Routing <Router AppAssembly="typeof(Program).Assembly"> <Found Context="routeData"> <RouteView RouteData="routeData" /> </Found> <NotFound> <h1>Page not found</h1> <p>Sorry, but there's nothing here!</p> </NotFound> </Router>
Agregue una página
_Host
al proyecto con el contenido siguiente.Pages/_Host.cshtml
:@page "/blazor" @{ Layout = "_Layout"; } <app> <component type="typeof(App)" render-mode="ServerPrerendered" /> </app>
Los componentes usan el archivo compartido
_Layout.cshtml
para su diseño.RenderMode configura si el componente
App
:- Se representa previamente en la página.
- Se representa como HTML estático en la página o si incluye la información necesaria para arrancar una aplicación Blazor desde el agente de usuario.
Para obtener más información sobre el asistente de etiquetas de componentes, como pasar parámetros y configurar RenderMode, vea Asistente de etiquetas de componente en ASP.NET Core.
En los puntos de conexión
Startup.Configure
deStartup.cs
, agregue una ruta de prioridad baja para la página_Host
como último punto de conexión:endpoints.MapFallbackToPage("/_Host");
En el ejemplo siguiente se muestra la línea agregada en la configuración del punto de conexión de una aplicación típica:
app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); endpoints.MapBlazorHub(); endpoints.MapFallbackToPage("/_Host"); });
Agregue componentes enrutables al proyecto.
Pages/RoutableCounter.razor
:@page "/routable-counter" <h1>Routable Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
Ejecuta el proyecto y ve al componente
RoutableCounter
enrutable en/routable-counter
.
Para obtener más información sobre los espacios de nombres, consulta la sección Espacios de nombres de componentes.
Uso de componentes enrutables en una aplicación MVC
Esta sección pertenece a la incorporación de componentes que se pueden enrutar directamente desde las solicitudes del usuario.
Para admitir componentes Razor enrutables en aplicaciones MVC, haga lo siguiente:
Sigue las instrucciones de la sección Configuración.
Agrega un componente
App
a la raíz del proyecto con el contenido siguiente.App.razor
:@using Microsoft.AspNetCore.Components.Routing <Router AppAssembly="typeof(Program).Assembly"> <Found Context="routeData"> <RouteView RouteData="routeData" /> </Found> <NotFound> <h1>Page not found</h1> <p>Sorry, but there's nothing here!</p> </NotFound> </Router>
Agregue una vista
_Host
al proyecto con el contenido siguiente.Views/Home/_Host.cshtml
:@{ Layout = "_Layout"; } <app> <component type="typeof(App)" render-mode="ServerPrerendered" /> </app>
Los componentes usan el archivo compartido
_Layout.cshtml
para su diseño.RenderMode configura si el componente
App
:- Se representa previamente en la página.
- Se representa como HTML estático en la página o si incluye la información necesaria para arrancar una aplicación Blazor desde el agente de usuario.
Para obtener más información sobre el asistente de etiquetas de componentes, como pasar parámetros y configurar RenderMode, consulta Asistente de etiquetas de componente en ASP.NET Core.
Agrega una acción al controlador Home.
Controllers/HomeController.cs
:public IActionResult Blazor() { return View("_Host"); }
En los puntos de conexión
Startup.Configure
deStartup.cs
, agregue una ruta de prioridad baja para la acción del controlador que devuelva la vista_Host
:endpoints.MapFallbackToController("Blazor", "Home");
En el ejemplo siguiente se muestra la línea agregada en la configuración del punto de conexión de una aplicación típica:
app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); endpoints.MapBlazorHub(); endpoints.MapFallbackToController("Blazor", "Home"); });
Agregue componentes enrutables al proyecto.
Pages/RoutableCounter.razor
:@page "/routable-counter" <h1>Routable Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
Ejecuta el proyecto y ve al componente
RoutableCounter
enrutable en/routable-counter
.
Para obtener más información sobre los espacios de nombres, consulta la sección Espacios de nombres de componentes.
Representación de componentes a partir de una página o vista
Esta sección pertenece a la adición de componentes a páginas o vistas, donde los componentes no son enrutables directamente desde las solicitudes del usuario.
Para representar un componente a partir de una página o vista, usa el asistente de etiquetas de componente.
Representación de componentes interactivos con estado
Los componentes interactivos con estado se pueden agregar a una página de Razor o una vista.
Cuando se representa la página o la vista:
- El componente se representa previamente con la página o la vista.
- Se pierde el estado inicial del componente que se usa para la representación previa.
- Cuando se establece la conexión SignalR, se crea un estado del componente.
La siguiente página de Razor representa un componente Counter
:
<h1>My Razor Page</h1>
<component type="typeof(Counter)" render-mode="ServerPrerendered"
param-InitialValue="InitialValue" />
@functions {
[BindProperty(SupportsGet=true)]
public int InitialValue { get; set; }
}
Para obtener más información, consulta Asistente de etiquetas de componente en ASP.NET Core.
Representación de componentes no interactivos
En la siguiente página de Razor, el componente Counter
se representa de forma estática con un valor inicial que se especifica mediante un formulario. Como el componente se representa de forma estática, no es interactivo:
<h1>My Razor Page</h1>
<form>
<input type="number" asp-for="InitialValue" />
<button type="submit">Set initial value</button>
</form>
<component type="typeof(Counter)" render-mode="Static"
param-InitialValue="InitialValue" />
@functions {
[BindProperty(SupportsGet=true)]
public int InitialValue { get; set; }
}
Para obtener más información, consulta Asistente de etiquetas de componente en ASP.NET Core.
Espacios de nombres de componentes
Si usas una carpeta personalizada para contener los componentes Razor del proyecto, agrega el espacio de nombres que representa la carpeta a la página o vista, o bien al archivo _ViewImports.cshtml
. En el ejemplo siguiente:
- Los componentes se almacenan en la carpeta
Components
del proyecto. - El marcador de posición
{APP NAMESPACE}
es el espacio de nombres del proyecto.Components
representa el nombre de la carpeta.
@using {APP NAMESPACE}.Components
El archivo _ViewImports.cshtml
se encuentra en la carpeta Pages
de una aplicación Razor Pages o en la carpeta Views
de una aplicación de MVC.
Para más información, vea Componentes Razor de ASP.NET Core.
Tamaño de estado antes de la representación y límite de tamaño del mensaje SignalR
Un tamaño grande de estado anterior a la representación puede superar el límite de tamaño del mensaje de circuito SignalR, lo que da como resultado lo siguiente:
- El circuito SignalR no se puede inicializar con un error en el cliente: Circuit host not initialized.
- La interfaz de usuario de reconexión del cliente aparece cuando se produce un error en el circuito. No es posible la recuperación.
Para resolver el problema, usa uno de los enfoques siguientes:
- Reduce la cantidad de datos que se están colocando en el estado anterior a la representación.
- Aumenta el límite de tamaño del mensajeSignalR. ADVERTENCIA: Aumentar el límite puede aumentar el riesgo de ataques por denegación de servicio (DoS).
Recursos de Blazor Server adicionales
- Administración de estados: control de la representación previa
- Temas del ciclo de vida de los componentes Razor relacionados con la representación previa
- Autenticación y autorización: aspectos generales
- Control de errores: representación previa de
- Hospedaje e implementación: Blazor Server
- Mitigación de amenazas: scripting entre sitios (XSS)