Migración de ASP.NET Core en .NET 7 a .NET 8

En este artículo se explica cómo actualizar un proyecto de ASP.NET Core 7.0 a ASP.NET Core 8.0.

Requisitos previos

Actualización de la versión del SDK de .NET en global.json

Si utiliza un archivo global.json para utilizar una versión específica del SDK de .NET Core, actualice la propiedad version a la versión del .NET SDK 8.0 instalada. Por ejemplo:

{
  "sdk": {
-    "version": "7.0.100"
+    "version": "8.0.100"
  }
}

Actualización de la plataforma de destino

Actualizar el archivo del proyecto del Moniker de la plataforma de destino (TFM) a net8.0:

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

  <PropertyGroup>
-    <TargetFramework>net7.0</TargetFramework>
+    <TargetFramework>net8.0</TargetFramework>
  </PropertyGroup>

</Project>

Actualización de las referencias del paquete

En el archivo del proyecto, actualice el atributo Version de cada paquete de referencia Microsoft.AspNetCore.*, Microsoft.EntityFrameworkCore.*, Microsoft.Extensions.* y System.Net.Http.Json a 8.00 o posterior. Por ejemplo:

<ItemGroup>
-   <PackageReference Include="Microsoft.AspNetCore.JsonPatch" Version="7.0.12" />
-   <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.12" />
-   <PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="7.0.0" />
-   <PackageReference Include="System.Net.Http.Json" Version="7.0.1" />
+   <PackageReference Include="Microsoft.AspNetCore.JsonPatch" Version="8.0.0" />
+   <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.0" />
+   <PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="8.0.0" />
+   <PackageReference Include="System.Net.Http.Json" Version="8.0.0" />
</ItemGroup>

Blazor

Se cubren los siguientes escenarios de migración:

Para obtener instrucciones sobre cómo agregar compatibilidad con Blazor a una aplicación de ASP.NET Core, consulte Integración de componentes de ASP.NET Core Razor en aplicaciones de ASP.NET Core.

Actualice una aplicación Blazor Server

Se recomienda usar Blazor Web Apps en .NET 8, pero Blazor Server se admite. Para seguir usando Blazor Server con .NET 8, siga las instrucciones de las tres primeras secciones de este artículo:

Las nuevas características Blazor introducidas para Blazor Web Apps no están disponibles para una aplicación Blazor Server actualizada para ejecutarse en .NET 8. Si desea adoptar las nuevas características de .NET 8 Blazor, siga las instrucciones de cualquiera de las siguientes secciones:

Adopte todas las convenciones de Blazor App Web

Para adoptar opcionalmente todas las nuevas convenciones de Blazor Web App, se recomienda el siguiente proceso:

  • Cree una nueva aplicación a partir de la plantilla de proyecto de Blazor Web App. Para más información, vea Herramientas para ASP.NET Core Blazor.
  • Mueva los componentes y el código de la aplicación a la nueva aplicación Blazor Web App, realizando modificaciones para adoptar nuevas características.
  • Actualice el diseño y los estilos de Blazor Web App.

Las nuevas características de .NET 8 se tratan en Novedades de ASP.NET Core 8.0. Al actualizar una aplicación desde .NET 6 o versiones anteriores, consulte las notas de la migración y la versión (artículos de Novedades) para las versiones intermedias.

Conversión de una aplicación Blazor Server en una Blazor Web App

Las aplicaciones Blazor Server admiten en .NET 8 sin cambios en el código. Use las instrucciones siguientes para convertir una aplicación Blazor Server una .NET 8 Blazor Web App equivalente, que hace que todas las nuevas características de .NET 8 estén disponibles.

Importante

Esta sección se centra en los cambios mínimos necesarios para convertir una aplicación de .NET 7 Blazor Server en una NET 8 Blazor Web App. Para adoptar todas las nuevas convenciones de Blazor Web App, siga las instrucciones de la sección Adopción de todas convenciones de Blazor Web App.

  1. Siga las instrucciones de las tres primeras secciones de este artículo:

  2. Mueva el contenido del componente App (App.razor) a un nuevo archivo de componente Routes (Routes.razor) agregado a la carpeta raíz del proyecto. Deje el archivo vacío App.razor en la aplicación en la carpeta raíz del proyecto.

  3. Agregue una entrada al archivo _Imports.razor para que los modos de representación abreviados estén disponibles para la aplicación:

    @using static Microsoft.AspNetCore.Components.Web.RenderMode
    
  4. Mueva el contenido de la página _Host (Pages/_Host.cshtml) al archivo vacío App.razor. Continúe para realizar los siguientes cambios en el componente App.

    Nota:

    En el ejemplo siguiente, el espacio de nombres del proyecto es BlazorServerApp. Ajuste el espacio de nombres para que coincida con el proyecto.

    Quite las siguientes líneas de la parte superior del archivo:

    - @page "/"
    - @using Microsoft.AspNetCore.Components.Web
    - @namespace BlazorServerApp.Pages
    - @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
    

    Reemplace las líneas anteriores por una línea que inserta una instancia de IHostEnvironment:

    @inject IHostEnvironment Env
    

    Quite la tilde (~) de la href de la etiqueta <base> y reemplace por la ruta de acceso base de la aplicación:

    - <base href="~/" />
    + <base href="/" />
    

    Quite el asistente de etiquetas de componente para el componente HeadOutlet y reemplácelo por el componente HeadOutlet.

    Quite las siguientes líneas:

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

    Reemplace la línea anterior por lo siguiente:

    <HeadOutlet @rendermode="InteractiveServer" />
    

    Quite el asistente de etiquetas de componente para el componente App y reemplácelo por el componente Routes.

    Quite las siguientes líneas:

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

    Reemplace la línea anterior por lo siguiente:

    <Routes @rendermode="InteractiveServer" />
    

    Nota:

    La configuración anterior supone que los componentes de la aplicación adoptan la representación interactiva del servidor. Para obtener más información, incluida la adopción de la representación de servidores estáticos (SSR), consulte modos de representación de ASP.NET Core Blazor.

    Quite los asistentes de etiquetas de entorno para la interfaz de usuario de error y reemplácelos por el marcado Razor siguiente.

    Quite las siguientes líneas:

    - <environment include="Staging,Production">
    -     An error has occurred. This application may no longer respond until reloaded.
    - </environment>
    - <environment include="Development">
    -     An unhandled exception has occurred. See browser dev tools for details.
    - </environment>
    

    Reemplace las líneas anteriores por lo siguiente:

    @if (Env.IsDevelopment())
    {
        <text>
            An unhandled exception has occurred. See browser dev tools for details.
        </text>
    }
    else
    {
        <text>
            An error has occurred. This app may no longer respond until reloaded.
        </text>
    }
    

    Cambie el script de Blazor de blazor.server.js a blazor.web.js:

    - <script src="_framework/blazor.server.js"></script>
    + <script src="_framework/blazor.web.js"></script>
    
  5. Elimine el archivo Pages/_Host.cshtml.

  6. Actualice Program.cs:

    Nota:

    En el ejemplo siguiente, el espacio de nombres del proyecto es BlazorServerApp. Ajuste el espacio de nombres para que coincida con el proyecto.

    Agregue una instrucción using a la parte superior del archivo para el espacio de nombres del proyecto:

    using BlazorServerApp;
    

    Reemplace AddServerSideBlazor con AddRazorComponents y una llamada encadenada a AddInteractiveServerComponents.

    Quite las siguientes líneas:

    - builder.Services.AddServerSideBlazor();
    

    Vuelva a colocar la línea anterior con componente Razor y servicios de componente de servidor interactivos. La llamada AddRazorComponents agrega servicios antiforgería (AddAntiforgery) de manera predeterminada.

    builder.Services.AddRazorComponents()
        .AddInteractiveServerComponents();
    

    Quite las siguientes líneas:

    - app.MapBlazorHub();
    

    Reemplace la línea anterior por una llamada a MapRazorComponents, proporcionando el componente App como el tipo de componente raíz y agregue una llamada encadenada a AddInteractiveServerRenderMode:

    app.MapRazorComponents<App>()
        .AddInteractiveServerRenderMode();
    

    Quite las siguientes líneas:

    - app.MapFallbackToPage("/_Host");
    

    Agregue Antiforgery Middleware a la canalización de procesamiento de solicitudes después de la llamada a app.UseRouting. Si hay llamadas a app.UseRouting y app.UseEndpoints, la llamada a app.UseAntiforgery debe ir entre ellas. Se debe realizar una llamada a app.UseAntiforgery después de las llamadas a app.UseAuthentication y app.UseAuthorization. No es necesario agregar servicios antiforgería (builder.Services.AddAntiforgery()), ya que se agregan automáticamente mediante AddRazorComponents, que se ha cubierto anteriormente.

    app.UseAntiforgery();
    
  7. Si la aplicación Blazor Server se configuró para deshabilitar la representación previa, puede continuar deshabilitando la representación previa de la aplicación actualizada. En el componente App, cambie el valor asignado a los atributos de directiva @rendermodeRazor para los componentes HeadOutlet y Routes.

    Cambie el valor del atributo de directiva @rendermode para los componentes HeadOutlet y Routes para deshabilitar la representación previa:

    - @rendermode="InteractiveServer"
    + @rendermode="new InteractiveServerRenderMode(prerender: false)"
    

    Para obtener más información, vea Modos de representación de ASP.NET CoreBlazor.

Actualice una aplicación Blazor WebAssembly

Siga las instrucciones de las tres primeras secciones de este artículo:

Conversión de una aplicación Blazor WebAssembly hospedada en una Blazor Web App

Las aplicaciones Blazor WebAssembly se admiten en .NET 8 sin cambios en el código. Use las instrucciones siguientes para convertir una aplicación Blazor WebAssembly hospedada de ASP.NET Core en una .NET 8 Blazor Web App equivalente, que hace que todas las nuevas características de .NET 8 estén disponibles.

Importante

Esta sección se centra en los cambios mínimos necesarios para convertir una aplicación Blazor WebAssembly hospedada en .NET 7 ASP.NET Core en una .NET 8 Blazor Web App. Para adoptar todas las nuevas convenciones de Blazor Web App, siga las instrucciones de la sección Adopción de todas convenciones de Blazor Web App.

  1. Siga las instrucciones de las tres primeras secciones de este artículo:

    Importante

    Con las instrucciones anteriores, actualice los proyectos de Client, Server y Shared.

  2. En el archivo de proyecto .Client (.csproj), agrega las siguientes propiedades de MS Build:

    <NoDefaultLaunchSettingsFile>true</NoDefaultLaunchSettingsFile>
    <StaticWebAssetProjectMode>Default</StaticWebAssetProjectMode>
    
  3. También en el archivo de proyecto .Client, quita la referencia de paquete Microsoft.AspNetCore.Components.WebAssembly.DevServer:

    - <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer"... />
    
  4. Mueva el contenido del archivo del archivo Client/wwwroot/index.html a un nuevo archivo de componentes App (App.razor) creado en la raíz del proyecto Server. Después de mover el contenido del archivo, elimine el archivo index.html.

  5. Cambie el nombre App.razor del proyecto .Client a Routes.razor.

  6. En Routes.razor, actualice el valor del atributo AppAssembly a typeof(Program).Assembly.

  7. Agregue una entrada al archivo _Imports.razor para que los modos de representación abreviados estén disponibles para la aplicación:

    @using static Microsoft.AspNetCore.Components.Web.RenderMode
    
  8. Realice una copia del archivo _Imports.razor y agréguelo al proyecto Server.

  9. Realice los cambios siguientes en el archivo App.razor:

    Reemplace la etiqueta <title> por los componentes HeadOutlet y PageTitle. Empiece quitando la etiqueta <title>. Anote el título para usarlo más adelante antes de quitar la etiqueta:

    - <title>...</title>
    

    Cambie el conjunto de estilos CSS:

    - <link href="{CLIENT PROJECT ASSEMBLY NAME}.styles.css" rel="stylesheet">
    + <link href="{SERVER PROJECT ASSEMBLY NAME}.styles.css" rel="stylesheet">
    

    Marcadores de posición del código anterior:

    • {CLIENT PROJECT ASSEMBLY NAME}: nombre del ensamblado del proyecto del cliente. Ejemplo: BlazorSample.Client
    • {SERVER PROJECT ASSEMBLY NAME}: nombre del ensamblado del proyecto del servidor. Ejemplo: BlazorSample

    Agregue el componente HeadOutlet al final del contenido del <head> con el modo interactivo de representación WebAssembly (representación previa deshabilitada). Además, agregue el componente PageTitle con el título de la aplicación:

    <HeadOutlet @rendermode="new InteractiveWebAssemblyRenderMode(prerender: false)" />
    <PageTitle>...</PageTitle>
    

    Para más información, vea Control del contenido principal en aplicaciones Blazor de ASP.NET Core.

    Busque el siguiente marcado HTML <div>...</div>:

    - <div id="app">
    -     ...
    - </div>
    

    Reemplace el marcado HTML <div>...</div> anterior por el componente Routes mediante el modo de representación WebAssembly interactivo (representación previa deshabilitada):

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

    Actualice el script blazor.webassembly.js a blazor.web.js:

    - <script src="_framework/blazor.webassembly.js"></script>
    + <script src="_framework/blazor.web.js"></script>
    
  10. Quite las siguientes líneas de Client/Program.cs:

    - builder.RootComponents.Add<App>("#app");
    - builder.RootComponents.Add<HeadOutlet>("head::after");
    
  11. Actualice Server/Program.cs:

    Agregue el componente Razor y servicios de componentes interactivos de WebAssembly al proyecto. Llame AddRazorComponents con una llamada encadenada a AddInteractiveWebAssemblyComponents. La llamada AddRazorComponents agrega servicios antiforgería (AddAntiforgery) de manera predeterminada.

    builder.Services.AddRazorComponents()
        .AddInteractiveWebAssemblyComponents();
    

    Agregue Antiforgery Middleware a la canalización de procesamiento de solicitudes.

    Coloque el siguiente código:

    • Después de la llamada a app.UseRouting.
    • Si hay llamadas a app.UseRouting y app.UseEndpoints, la llamada a app.UseAntiforgery debe ir entre ellas.
    • La llamada a app.UseAntiforgery debe realizarse después de una llamada a app.UseAuthorization, siempre que esté presente.
    • No es necesario agregar servicios antiforgería (builder.Services.AddAntiforgery()), ya que se agregan automáticamente mediante AddRazorComponents, que se ha cubierto anteriormente.
    app.UseAntiforgery();
    

    Quite las siguientes líneas:

    - app.UseBlazorFrameworkFiles();
    

    Quite las siguientes líneas:

    - app.MapFallbackToFile("index.html");
    

    Reemplace la línea anterior por una llamada a MapRazorComponents, proporcionando el componente App como el tipo de componente raíz y agregue llamadas encadenadas a AddInteractiveWebAssemblyRenderMode y AddAdditionalAssemblies:

    app.MapRazorComponents<App>()
        .AddInteractiveWebAssemblyRenderMode()
        .AddAdditionalAssemblies(typeof({CLIENT APP NAMESPACE}._Imports).Assembly);
    

    En el ejemplo anterior, el marcador de posición {CLIENT APP NAMESPACE} es el espacio de nombres del proyecto .Client (por ejemplo, HostedBlazorApp.Client). Reemplace el marcador de posición .Client por el espacio de nombres del proyecto.

  12. Ejecute la solución desde el proyecto Server:

    Para Visual Studio, confirme que el proyecto Server está seleccionado en el Explorador de soluciones al ejecutar la aplicación.

    Si usa la CLI de .NET, ejecute el proyecto desde la carpeta del proyecto Server.

Actualización de la configuración de la opción de servicio y punto de conexión

Con el lanzamiento de Blazor Web Apps en .NET 8, la configuración de la opción de servicio y punto de conexión Blazor se actualiza con la introducción de la nueva API para los servicios de componentes interactivos y la configuración del punto de conexión de componentes.

Las instrucciones de configuración actualizadas aparecen en las siguientes ubicaciones:

Anulación de Blazor Server con solución alternativa de enrutamiento de Yarp

Si anteriormente siguió las instrucciones de Habilitación de la compatibilidad de ASP.NET Core Blazor Server con Yarp en la migración incremental para migrar una aplicación Blazor Server con Yarp a .NET 6 o .NET 7, puede revertir los pasos de solución alternativa que ha realizado al seguir las instrucciones del artículo. El enrutamiento y la vinculación en profundidad para Blazor Server con Yarp funcionan correctamente en .NET 8.

Migración de componentes CascadingValue en los componentes de diseño

Los parámetros en cascada no pasan datos a través de los límites del modo de representación y los diseños se representan estáticamente en aplicaciones interactivas. Por lo tanto, las aplicaciones que buscan usar parámetros en cascada en componentes representados interactivamente no podrán aplicar en cascada los valores de un diseño.

Los dos enfoques para la migración son los siguientes:

Para obtener más información, consulte Valores y parámetros en cascada y límites de modo de representación.

Migración de la propiedad BlazorEnableCompression de MSBuild

En el caso de las aplicaciones Blazor WebAssembly que deshabilitan la compresión y tienen como destino .NET 7 o versiones anteriores, pero que se crean con el SDK de .NET 8, la propiedad BlazorEnableCompression de MSBuild ha cambiado a CompressionEnabled:

<PropertyGroup>
-   <BlazorEnableCompression>false</BlazorEnableCompression>
+   <CompressionEnabled>false</CompressionEnabled>
</PropertyGroup>

Al usar el comando publish de la CLI de .NET, use la nueva propiedad:

dotnet publish -p:CompressionEnabled=false

Para obtener más información, consulte los siguientes recursos:

Migración del componente <CascadingAuthenticationState> en los servicios de estado de autenticación en cascada

En .NET 7 o versiones anteriores, el componente CascadingAuthenticationState se ajusta alrededor de alguna parte del árbol de la interfaz de usuario, por ejemplo, alrededor del enrutador Blazor, para proporcionar el estado de autenticación en cascada:

<CascadingAuthenticationState>
    <Router ...>
        ...
    </Router>
</CascadingAuthenticationState>

En .NET 8, no use el componente CascadingAuthenticationState:

- <CascadingAuthenticationState>
      <Router ...>
          ...
      </Router>
- </CascadingAuthenticationState>

En su lugar, agregue servicios de estado de autenticación en cascada a la colección de servicios mediante una llamada a AddCascadingAuthenticationState en el archivo Program:

builder.Services.AddCascadingAuthenticationState();

Para obtener más información, consulte los siguientes recursos:

Nuevo artículo sobre problemas de almacenamiento en caché HTTP

Hemos agregado un nuevo artículo en el que se describen algunos de los problemas comunes de almacenamiento en caché HTTP que pueden producirse al actualizar aplicaciones de Blazor entre versiones principales y cómo solucionar problemas de almacenamiento en caché HTTP.

Para obtener más información, consulte Evitar problemas de almacenamiento en caché HTTP al actualizar aplicaciones ASP.NET Core Blazor.

Nuevo artículo sobre bibliotecas de clases con representación estática del lado servidor (SSR estático)

Hemos agregado un nuevo artículo en el que se describe la autoría de la biblioteca de componentes en las bibliotecas de clases de Razor (RCL) con la representación estática del lado servidor (SSR estático).

Para obtener más información, consulte Bibliotecas de clases de ASP.NET Core (RCL) Razor con representación estática del lado servidor (SSR estático).

Detección de componentes de ensamblados adicionales

Al migrar de una aplicación Blazor Server a una aplicación web Blazor, acceda a la guía de Enrutamiento y navegación de ASP.NET Core Blazor si la aplicación usa componentes enrutables de ensamblados adicionales, como bibliotecas de clases de componentes.

Quitar el atributo [Parameter] cuando se proporciona el parámetro desde una cadena de consulta

El atributo [Parameter] ya no es necesario al proporcionar un parámetro de la cadena de consulta:

- [Parameter]
  [SupplyParameterFromQuery]

Autorización de directiva de reserva de scripts de Blazor Server

En .NET 7, el script de Blazor Server (blazor.server.js) se sirve mediante middleware de archivos estáticos. La colocación de la llamada al middleware de archivos estáticos (UseStaticFiles) en la canalización de procesamiento de solicitudes antes de la llamada al middleware de autorización (UseAuthorization) es suficiente en las aplicaciones de .NET 7 para servir el script de Blazor a usuarios anónimos.

En .NET 8, el script de Blazor Server se sirve por su propio punto de conexión, mediante el enrutamiento de puntos de conexión. Este cambio se introduce mediante Error corregido: pasar opciones a UseStaticFiles interrumpe Blazor Server (dotnet/aspnetcore #45897).

Considere un escenario multiinquilino en el que:

  • Las directivas predeterminadas y de reserva se establecen de forma idéntica.
  • El inquilino se resuelve mediante el primer segmento de la ruta de solicitud (por ejemplo, tld.com/tenant-name/...).
  • Las solicitudes a los puntos de conexión de inquilino se autentican mediante un esquema de autenticación adicional, que agrega una identidad adicional a la entidad de seguridad de la solicitud.
  • La directiva de autorización de reserva tiene requisitos que comprueban las notificaciones a través de la identidad adicional.

Las solicitudes del archivo de script de Blazor (blazor.server.js) se sirven en /_framework/blazor.server.js, que está protegido en el marco. Las solicitudes del archivo no están autenticadas por el esquema de autenticación adicional para los inquilinos pero siguen siendo cuestionadas por la directiva de reserva, lo cual da como resultado la devolución de un resultado no autorizado.

Este problema está bajo evaluación para una nueva característica del marco en Asignar componentes de Razor dañados con FallbackPolicy RequireAuthenticatedUser (dotnet/aspnetcore 51836), que actualmente está programado para la versión de .NET 9 en noviembre de 2024. Hasta entonces, puede solucionar este problema mediante cualquiera de los tres enfoques siguientes:

  • No use una directiva de reserva. Aplique el atributo [Authorize] en el archivo _Imports.razor para aplicarlo a todos los componentes de la aplicación. Para los puntos de conexión que no son de Blazor, use explícitamente [Authorize] o RequireAuthorization.

  • Agregue [AllowAnonymous] al punto de conexión /_framework/blazor.server.js en el archivo Program:

    app.MapBlazorHub().Add(endpointBuilder =>
    {
        if (endpointBuilder is 
            RouteEndpointBuilder
            { 
                RoutePattern: { RawText: "/_framework/blazor.server.js" }
            })
        {
            endpointBuilder.Metadata.Add(new AllowAnonymousAttribute());
        }
    });
    
  • Registre un AuthorizationHandler personalizado que compruebe HttpContext para permitir el paso del archivo /_framework/blazor.server.js.

Docker

Actualización de imágenes de Docker

En el caso de las aplicaciones que usan Docker, actualice las instrucciones y scripts de DockerfileFROM. Use una imagen de base que incluya el runtime de ASP.NET Core 8.0. Tenga en cuenta la siguiente diferencia en el comando docker pull entre ASP.NET Core 7.0 y 8.0:

- docker pull mcr.microsoft.com/dotnet/aspnet:7.0
+ docker pull mcr.microsoft.com/dotnet/aspnet:8.0

Actualizar el puerto de Docker

El puerto de ASP.NET Core predeterminado configurado en imágenes de contenedor de .NET se ha actualizado del puerto 80 al 8080.

La nueva variable de entorno ASPNETCORE_HTTP_PORTS se agregó como alternativa más sencilla a ASPNETCORE_URLS.

Para más información, vea:

Revisar cambios importantes

Para consultar los cambios importantes de .NET Core .NET 7.0 a 8.0, vea Cambios importantes en .NET 8, que incluye secciones de ASP.NET Core y Entity Framework Core.