Migración de ASP.NET Core 2.2 a 3.0

Por Scott Addie y Rick Anderson

En este artículo se explica cómo actualizar un proyecto ASP.NET Core 2.2 existente a ASP.NET Core 3.0. Puede resultar útil crear un nuevo proyecto ASP.NET Core 3.0 para:

  • Compare con el código ASP.NET Core 2.2.
  • Copie los cambios pertinentes en el proyecto ASP.NET Core 3.0.

Requisitos previos

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

Si la solución se basa en un archivo global.js para tener como destino una versión específica de SDK de .NET Core, actualice su propiedad a la version versión 3.0 instalada en el equipo:

{
  "sdk": {
    "version": "3.0.100"
  }
}

Actualización del archivo de proyecto

Actualización de la plataforma de destino

ASP.NET Core 3.0 y versiones posteriores solo se ejecutan en .NET Core. Establezca el Moniker de la plataforma de destino (TFM) en netcoreapp3.0 :

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

  <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
  </PropertyGroup>

</Project>

Eliminación de referencias de paquete obsoletas

Un gran número de NuGet paquetes no se generan para ASP.NET Core 3.0. Estas referencias de paquete deben quitarse del archivo del proyecto. Considere el siguiente archivo de proyecto para una ASP.NET Core web 2.2:

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

  <PropertyGroup>
    <TargetFramework>netcoreapp2.2</TargetFramework>
    <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.App"/>
    <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
  </ItemGroup>

</Project>

El archivo de proyecto actualizado para ASP.NET Core 3.0:

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

  <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
  </PropertyGroup>

</Project>

Archivo de proyecto ASP.NET Core 3.0 actualizado:

  • En <PropertyGroup>:

    • Actualiza el TFM a netcoreapp3.0
    • Quita el <AspNetCoreHostingModel> elemento . Para obtener más información, vea Modelo de hospedaje en proceso en este documento.
  • En <ItemGroup>:

    • Microsoft.AspNetCore.App se quita. Para obtener más información, vea Referencia de Framework en este documento.
    • Microsoft.AspNetCore.Razor.Design se quita y en la siguiente lista de paquetes ya no se generan.

Para ver la lista completa de paquetes que ya no se generan, seleccione la siguiente lista de expansión:

Haga clic para expandir la lista de paquetes que ya no se generan.
  • Microsoft.AspNetCore
  • Microsoft.AspNetCore.All
  • Microsoft.AspNetCore.App
  • Microsoft.AspNetCore.Antiforgery
  • Microsoft.AspNetCore.Authentication
  • Microsoft.AspNetCore.Authentication.Abstractions
  • Microsoft.AspNetCore.Authentication. Cookie s
  • Microsoft.AspNetCore.Authentication.Core
  • Microsoft.AspNetCore.Authentication.OAuth
  • Microsoft.AspNetCore.Authorization.Policy
  • Microsoft.AspNetCore. Cookie Política
  • Microsoft.AspNetCore.Cors
  • Microsoft.AspNetCore.Diagnostics
  • Microsoft.AspNetCore.Diagnostics.HealthChecks
  • Microsoft.AspNetCore.HostFiltering
  • Microsoft.AspNetCore.Hosting
  • Microsoft.AspNetCore.Hosting.Abstractions
  • Microsoft.AspNetCore.Hosting.Server.Abstractions
  • Microsoft.AspNetCore.Http
  • Microsoft.AspNetCore.Http.Abstractions
  • Microsoft.AspNetCore.Http.Connections
  • Microsoft.AspNetCore.Http.Extensions
  • Microsoft.AspNetCore.HttpOverrides
  • Microsoft.AspNetCore.HttpsPolicy
  • Microsoft.AspNetCore.Identity
  • Microsoft.AspNetCore.Localization
  • Microsoft.AspNetCore.Localization.Routing
  • Microsoft.AspNetCore.Mvc
  • Microsoft.AspNetCore.Mvc.Abstractions
  • Microsoft.AspNetCore.Mvc.Analyzers
  • Microsoft.AspNetCore.Mvc.ApiExplorer
  • Microsoft.AspNetCore.Mvc.Api.Analyzers
  • Microsoft.AspNetCore.Mvc.Core
  • Microsoft.AspNetCore.Mvc.Cors
  • Microsoft.AspNetCore.Mvc.DataAnnotations
  • Microsoft.AspNetCore.Mvc.Formatters.Json
  • Microsoft.AspNetCore.Mvc.Formatters.Xml
  • Microsoft.AspNetCore.Mvc.Localization
  • Microsoft.AspNetCore.Mvc.Razor
  • Microsoft.AspNetCore.Mvc. Razor . ViewCompilation
  • Microsoft.AspNetCore.Mvc. Razor Páginas
  • Microsoft.AspNetCore.Mvc.TagHelpers
  • Microsoft.AspNetCore.Mvc.ViewFeatures
  • Microsoft.AspNetCore.Razor
  • Microsoft.AspNetCore. Razor . Ejecución
  • Microsoft.AspNetCore. Razor . Diseño
  • Microsoft.AspNetCore.ResponseCaching
  • Microsoft.AspNetCore.ResponseCaching.Abstractions
  • Microsoft.AspNetCore.ResponseCompression
  • Microsoft.AspNetCore.Rewrite
  • Microsoft.AspNetCore.Routing
  • Microsoft.AspNetCore.Routing.Abstractions
  • Microsoft.AspNetCore.Server.HttpSys
  • Microsoft.AspNetCore.Server.IIS
  • Microsoft.AspNetCore.Server.IISIntegration
  • Microsoft.AspNetCore.Server.Kestrel
  • Microsoft.AspNetCore.Server. Kestrel . Núcleo
  • Microsoft.AspNetCore.Server. Kestrel . Https
  • Microsoft.AspNetCore.Server. Kestrel . Transport.Abstractions
  • Microsoft.AspNetCore.Server. Kestrel . Transport.Sockets
  • Microsoft.AspNetCore.Session
  • Microsoft.AspNetCore.SignalR
  • Microsoft.AspNetCore. SignalR . Núcleo
  • Microsoft.AspNetCore.StaticFiles
  • Microsoft.AspNetCore.WebSockets
  • Microsoft.AspNetCore.WebUtilities
  • Microsoft.Net.Http.Headers

Revisión de cambios importantes

Revisión de cambios importantes

Referencia del marco

Las características de ASP.NET Core que estaban disponibles a través de uno de los paquetes enumerados anteriormente están disponibles como parte del Microsoft.AspNetCore.App marco compartido. El marco compartido es el conjunto de ensamblados (archivos .dll) que se instalan en la máquina e incluye un componente de entorno de ejecución y un paquete de destino. Para más información, consulte este artículo sobre el marco de trabajo compartido.

  • Los proyectos que tienen como destino el SDK de Microsoft.NET.Sdk.Web hacen referencia implícitamente al marco Microsoft.AspNetCore.App.

    No se requieren referencias adicionales para estos proyectos:

    <Project Sdk="Microsoft.NET.Sdk.Web">
      <PropertyGroup>
        <TargetFramework>netcoreapp3.0</TargetFramework>
      </PropertyGroup>
        ...
    </Project>
    
  • Los proyectos que Microsoft.NET.Sdk tienen como destino o SDK deben agregar un explícito a Microsoft.NET.Sdk.Razor FrameworkReference Microsoft.AspNetCore.App :

    <Project Sdk="Microsoft.NET.Sdk.Razor">
      <PropertyGroup>
        <TargetFramework>netcoreapp3.0</TargetFramework>
      </PropertyGroup>
    
      <ItemGroup>
        <FrameworkReference Include="Microsoft.AspNetCore.App" />
      </ItemGroup>
        ...
    </Project>
    

Compilaciones dependientes del marco de trabajo con Docker

Las compilaciones dependientes del marco de trabajo de las aplicaciones de consola que usan un paquete que depende del marco ASP.NET Core compartido pueden producir el siguiente error en tiempo de ejecución:

It was not possible to find any compatible framework version
The specified framework 'Microsoft.AspNetCore.App', version '3.0.0' was not found.
  - No frameworks were found.

Microsoft.AspNetCore.Appes el marco compartido que contiene ASP.NET Core runtime y solo está presente en la imagen de Docker dotnet/core/aspnet. El SDK 3.0 reduce el tamaño de las compilaciones dependientes del marco de trabajo mediante ASP.NET Core al no incluir copias duplicadas de las bibliotecas que están disponibles en el marco compartido. Se trata de un ahorro potencial de hasta 18 MB, pero requiere que el entorno de ejecución ASP.NET Core esté presente o instalado para ejecutar la aplicación.

Para determinar si la aplicación tiene una dependencia (directa o indirecta) en el marco compartido de ASP.NET Core, examine elruntimeconfig.jsen el archivo generado durante una compilación o publicación de la aplicación. El siguiente archivo JSON muestra una dependencia en el marco ASP.NET Core compartido:

{
  "runtimeOptions": {
    "tfm": "netcoreapp3.0",
    "framework": {
      "name": "Microsoft.AspNetCore.App",
      "version": "3.0.0"
    },
    "configProperties": {
      "System.GC.Server": true
    }
  }
}

Si la aplicación usa Docker, use una imagen base que incluya ASP.NET Core 3.0. Por ejemplo, docker pull mcr.microsoft.com/dotnet/core/aspnet:3.0.

Agregar referencias de paquete para ensamblados quitados

ASP.NET Core 3.0 quita algunos ensamblados que anteriormente formaban parte de la referencia Microsoft.AspNetCore.App del paquete. Para visualizar qué ensamblados se quitaron, compare las dos carpetas del marco compartido. Por ejemplo, una comparación de las versiones 2.2.7 y 3.0.0:

comparación de ensamblados de marco compartido

Para seguir usando las características proporcionadas por los ensamblados quitados, haga referencia a las versiones 3.0 de los paquetes correspondientes:

Cambios de inicio

En la imagen siguiente se muestran las líneas eliminadas y modificadas en una ASP.NET Core web de Pages 2.2: Razor

las líneas eliminadas y cambiadas en una ASP.NET Core 2.2 Razor Aplicación web

En la imagen anterior, el código eliminado se muestra en rojo. El código eliminado no muestra el código cookie de opciones, que se eliminó antes de comparar los archivos.

En la imagen siguiente se muestran las líneas agregadas y modificadas en una ASP.NET Core web de Pages 3.0: Razor

las líneas agregadas y cambiadas en un ASP.NET Core 3.0 Razor Aplicación web

En la imagen anterior, el código agregado se muestra en verde. Para obtener información sobre los siguientes cambios:

  • services.AddMvc para services.AddRazorPages , vea Registro del servicio MVC en este documento.
  • CompatibilityVersion, vea Versión de compatibilidad para ASP.NET Core MVC .
  • IHostingEnvironmenta IWebHostEnvironment , vea este GitHub anuncio.
  • app.UseAuthorization se agregó a las plantillas para mostrar que se debe agregar el middleware de autorización de pedidos. Si la aplicación no usa la autorización, puede quitar de forma segura la llamada a app.UseAuthorization .
  • app.UseEndpoints, consulte Razor Pages o Migrate Startup.Configen este documento.

Compatibilidad con analizadores

Los proyectos que tienen como destino los analizadores de referencia implícita se enviaron anteriormente como parte del Microsoft.NET.Sdk.Web paquete Microsoft.AspNetCore.Mvc.Analyzers. No se requieren referencias adicionales para habilitar estas.

Si la aplicación usa analizadores de API enviados previamente mediante el paquete Microsoft.AspNetCore.Mvc.Api.Analyzers, edite el archivo de proyecto para hacer referencia a los analizadores incluidos como parte del SDK web de .NET Core:

<Project Sdk="Microsoft.NET.Sdk.Web">
    <PropertyGroup>
        <TargetFramework>netcoreapp3.0</TargetFramework>
        <IncludeOpenAPIAnalyzers>true</IncludeOpenAPIAnalyzers>
    </PropertyGroup>

    ...
</Project>

Razor Biblioteca de clases

Razor Los proyectos de biblioteca de clases que proporcionan componentes de interfaz de usuario para MVC deben establecer AddRazorSupportForMvc la propiedad en el archivo de proyecto:

<PropertyGroup>
  <AddRazorSupportForMvc>true</AddRazorSupportForMvc>
</PropertyGroup>

Modelo de hospedaje en proceso

El valor predeterminado de los proyectos es el modelo de hospedaje en proceso ASP.NET Core 3.0 o posterior. Opcionalmente, puede quitar la <AspNetCoreHostingModel> propiedad en el archivo de proyecto si su valor es InProcess .

Kestrel

Configuración

Migrar Kestrel la configuración al generador de host web proporcionado por ConfigureWebHostDefaults (Program.cs):

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.ConfigureKestrel(serverOptions =>
            {
                // Set properties and call methods on options
            })
            .UseStartup<Startup>();
        });

Si la aplicación crea el host manualmente con en ConfigureWebHost lugar de , llame a en el generador de host ConfigureWebHostDefaults UseKestrel web:

public static void Main(string[] args)
{
    var host = new HostBuilder()
        .UseContentRoot(Directory.GetCurrentDirectory())
        .ConfigureWebHost(webBuilder =>
        {
            webBuilder.UseKestrel(serverOptions =>
            {
                // Set properties and call methods on options
            })
            .UseIISIntegration()
            .UseStartup<Startup>();
        })
        .Build();

    host.Run();
}

Middleware de conexión reemplaza adaptadores de conexión

Los adaptadores de conexión ( Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal.IConnectionAdapter ) se han quitado de Kestrel . Reemplace los adaptadores de conexión por middleware de conexión. El middleware de conexión es similar al middleware HTTP en la ASP.NET Core, pero para las conexiones de nivel inferior. HTTPS y registro de conexiones:

  • Se han movido de adaptadores de conexión a middleware de conexión.
  • Estos métodos de extensión funcionan como en versiones anteriores de ASP.NET Core.

Para obtener más información, vea el ejemplo TlsFilterConnectionHandler en la sección ListenOptions.Protocols del Kestrel artículo.

Abstracciones de transporte movida y pública

La capa de transporte de Kestrel se ha expuesto como una interfaz pública en Connections.Abstractions. Como parte de estas actualizaciones:

  • Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions y se han quitado los tipos asociados.
  • NoDelay se ha movido de ListenOptions a las opciones de transporte.
  • Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal.SchedulingMode se quitó de KestrelServerOptions .

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

Kestrel Encabezados de finalizador de solicitud

Para las aplicaciones destinadas a versiones anteriores de ASP.NET Core:

  • Kestrel agrega encabezados de finalizador fragmentados HTTP/1.1 a la colección de encabezados de solicitud.
  • Los finalizadores están disponibles después de que el cuerpo de la solicitud se lea hasta el final.

Esto provoca algunas preocupaciones sobre la ambigüedad entre encabezados y finalizadores, por lo que los finalizadores se han movido a una nueva colección ( RequestTrailerExtensions ) en la versión 3.0.

Los finalizadores de solicitudes HTTP/2 son:

  • No está disponible en ASP.NET Core 2.2.
  • Disponible en 3.0 como RequestTrailerExtensions .

Existen nuevos métodos de extensión de solicitud para acceder a estos finalizadores. Al igual que con HTTP/1.1, los finalizadores están disponibles después de que el cuerpo de la solicitud se lea hasta el final.

Para la versión 3.0, están disponibles los RequestTrailerExtensions métodos siguientes:

  • GetDeclaredTrailers: obtiene el encabezado Trailer de solicitud que enumera los finalizadores que se esperan después del cuerpo.
  • SupportsTrailers: indica si la solicitud admite la recepción de encabezados de finalizador.
  • CheckTrailersAvailable: comprueba si la solicitud admite finalizadores y si están disponibles para leerse. Esta comprobación no supone que hay finalizadores para leer. Es posible que no haya ningún finalizador para leer aunque este método true lo devuelva.
  • GetTrailer: obtiene el encabezado final solicitado de la respuesta. Compruebe antes de llamar a o si la solicitud no SupportsTrailers GetTrailer admite NotSupportedException encabezados finales.

Para obtener más información, vea [Put request trailers in a separate collection (dotnet/AspNetCore #10410) Colocarfinalizadores de solicitud en una colección independiente (dotnet/AspNetCore #10410)].

AllowSynchronousIO deshabilitado

AllowSynchronousIO habilita o deshabilita las API de E/S sincrónicas, como HttpRequest.Body.Read HttpResponse.Body.Write , y Stream.Flush . Estas API son un origen de la escasez de subprocesos que conduce a bloqueos de aplicaciones. En la versión 3.0, AllowSynchronousIO se ha deshabilitado de manera predeterminada. Para obtener más información, vea la sección E/S sincrónica del Kestrel artículo.

Si se necesita E/S sincrónica, se puede habilitar configurando la opción en el servidor que se usa (al llamar a , por ejemplo, si AllowSynchronousIO ConfigureKestrel se usa Kestrel ). Tenga en cuenta que todos los servidores Kestrel (, HttpSys, TestServer, etc.) tienen su propia opción que no afectará AllowSynchronousIO a otros servidores. La E/S sincrónica se puede habilitar para todos los servidores por solicitud mediante la IHttpBodyControlFeature.AllowSynchronousIO opción :

var syncIOFeature = HttpContext.Features.Get<IHttpBodyControlFeature>();

if (syncIOFeature != null)
{
    syncIOFeature.AllowSynchronousIO = true;
}

Si tiene problemas con implementaciones u otras secuencias que llaman a api sincrónicas en TextWriter Dispose,llame a la nueva API en DisposeAsync su lugar.

Para obtener más información, vea [Anuncio] AllowSynchronousIO deshabilitadoen todos los servidores (dotnet/AspNetCore #7644).

Almacenamiento en búfer del formateador de salida

Newtonsoft.Jsen XmlSerializer los formateadores de salida basados en , DataContractSerializer y solo admiten la serialización sincrónica. Para permitir que estos formateadores funcionen con las restricciones AllowSynchronousIO del servidor, MVC almacena en búfer la salida de estos formateadores antes de escribir en el disco. Como resultado del almacenamiento en búfer, MVC incluirá el encabezado Content-Length al responder mediante estos formateadores.

System.Text.Json admite la serialización asincrónica y, por consiguiente, System.Text.Json el formateador basado no almacena en búfer. Considere la posibilidad de usar este formateador para mejorar el rendimiento.

Para deshabilitar el almacenamiento en búfer, las aplicaciones pueden SuppressOutputFormatterBuffering configurar en su inicio:

services.AddControllers(options => options.SuppressOutputFormatterBuffering = true)

Tenga en cuenta que esto puede dar lugar a que la aplicación produce una excepción en tiempo de ejecución si AllowSynchronousIO no está también configurada.

Microsoft.AspNetCore.Server. Kestrel . Ensamblado Https quitado

En ASP.NET Core 2.1, el contenido de Microsoft.AspNetCore.Server. Kestrel.Https.dll se movió a Microsoft.AspNetCore.Server. Kestrel.Core.dll. Se trata de una actualización sin cambios con TypeForwardedTo atributos. Para la versión 3.0, se han quitado el ensamblado.Https.dllvacío Microsoft.AspNetCore.Server y Kestrel el NuGet paquete.

Bibliotecas que hacen referencia a Microsoft.AspNetCore.Server. Kestrel . Https debe actualizar ASP.NET Core dependencias a la versión 2.1 o posterior.

Las aplicaciones y bibliotecas que tienen como destino ASP.NET Core 2.1 o posterior deben quitar las referencias directas a Microsoft.AspNetCore.Server. Kestrel Paquete Https.

Newtonsoft.Jscompatibilidad con (Json.NET)

Como parte del trabajo para mejorar el marco ASP.NET Core compartido,Newtonsoft.Jsen (Json.NET) se ha quitado del marco ASP.NET Core compartido.

El serializador JSON predeterminado para ASP.NET Core es System.Text.Json ahora , que es nuevo en .NET Core 3.0. Considere la posibilidad System.Text.Json de usar cuando sea posible. Es de alto rendimiento y no requiere una dependencia de biblioteca adicional. Sin embargo, dado que es nueva, es posible que falte actualmente System.Text.Json características que la aplicación necesita. Para obtener más información, vea How to migrate from Newtonsoft.Json to System.Text.Json (Cómomigrar de Newtonsoft.Jsa System.Text.Jsen ).

Uso Newtonsoft.Jsen un proyecto ASP.NET Core 3.0 SignalR

  • Instale Microsoft.AspNetCore. SignalR . Protocolos.NewtonsoftJson NuGet paquete.

  • En el cliente, encadenar una AddNewtonsoftJsonProtocol llamada de método a la instancia de HubConnectionBuilder :

    new HubConnectionBuilder()
        .WithUrl("/chathub")
        .AddNewtonsoftJsonProtocol(...)
        .Build();
    
  • En el servidor, encadenar una AddNewtonsoftJsonProtocol llamada de método a la llamada de método en AddSignalR Startup.ConfigureServices :

    services.AddSignalR()
        .AddNewtonsoftJsonProtocol(...);
    

Usar Newtonsoft.Jsen en un proyecto ASP.NET Core MVC de ASP.NET Core 3.0

  • Instale el Microsoft.AspNetCore.Mvc.NewtonsoftJson paquete.

  • Actualice Startup.ConfigureServices para llamar a AddNewtonsoftJson .

    services.AddMvc()
        .AddNewtonsoftJson();
    

    AddNewtonsoftJson es compatible con los nuevos métodos de registro del servicio MVC:

    • AddRazorPages
    • AddControllersWithViews
    • AddControllers
    services.AddControllers()
        .AddNewtonsoftJson();
    

    Newtonsoft.Json la configuración se puede establecer en la llamada a AddNewtonsoftJson :

    services.AddMvc()
        .AddNewtonsoftJson(options =>
               options.SerializerSettings.ContractResolver =
                  new CamelCasePropertyNamesContractResolver());
    

    Nota: Si el AddNewtonsoftJson método no está disponible, asegúrese de que ha instalado el Microsoft.AspNetCore.Mvc.NewtonsoftJson paquete. Un error común es instalar elNewtonsoft.Js en el paquete en lugar del Microsoft.AspNetCore.Mvc.NewtonsoftJson paquete.

Para obtener más información, consulte Agregar Newtonsoft.Jscompatibilidad con formato JSON basado en.

Registro del servicio MVC

ASP.NET Core 3.0 agrega nuevas opciones para registrar escenarios de MVC dentro de Startup.ConfigureServices .

Hay disponibles tres nuevos métodos de extensión de nivel superior relacionados con escenarios de MVC IServiceCollection en . Las plantillas usan estos nuevos métodos en lugar de AddMvc . Sin embargo, AddMvc sigue comportando como lo ha hecho en versiones anteriores.

En el ejemplo siguiente se agrega compatibilidad con controladores y características relacionadas con la API, pero no con vistas ni páginas. La plantilla de API usa este código:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
}

En el ejemplo siguiente se agrega compatibilidad con controladores, características relacionadas con la API y vistas, pero no con páginas. La plantilla aplicación web (MVC) usa este código:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
}

En el ejemplo siguiente se agrega compatibilidad con Razor Pages y compatibilidad mínima con el controlador. La plantilla Aplicación web usa este código:

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();
}

Los nuevos métodos también se pueden combinar. El ejemplo siguiente es equivalente a llamar AddMvc a en ASP.NET Core 2.2:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
    services.AddRazorPages();
}

Enrutamiento del código de inicio

Si una aplicación llama a UseMvc o UseSignalR , migre la aplicación a Endpoint Routing si es posible. Para mejorar la compatibilidad de Endpoint Routing con versiones anteriores de MVC, hemos revertido algunos de los cambios en la generación de direcciones URL introducidos en ASP.NET Core 2.2. Si ha experimentado problemas al usar El enrutamiento de puntos de conexión en la versión 2.2, espere mejoras en ASP.NET Core 3.0 con las siguientes excepciones:

  • Si la aplicación implementa o IRouter hereda de Route , use DynamicRouteValuesTransformer como reemplazo.
  • Si la aplicación accede directamente dentro de MVC para analizar direcciones URL, puede reemplazarlo por el uso de RouteData.Routers LinkParser.ParsePathByEndpointName.
    • Defina la ruta con un nombre de ruta.
    • Use LinkParser.ParsePathByEndpointName y pase el nombre de ruta deseado.

Endpoint Routing admite la misma sintaxis de patrón de ruta y las mismas características de creación de patrones de ruta que IRouter . El enrutamiento de puntos de conexión admite IRouteConstraint . El enrutamiento de puntos [Route] de conexión admite , y los demás atributos de enrutamiento de [HttpGet] MVC.

Para la mayoría de las aplicaciones, Startup solo se requieren cambios.

Migración Startup.Configure

Consejos generales:

  • Agregue UseRouting.

  • Si la aplicación llama a UseStaticFiles , coloque antes UseStaticFiles de UseRouting .

  • Si la aplicación usa características de autenticación/autorización como o , coloque la llamada a y : después de AuthorizePage y , pero antes de [Authorize] UseAuthentication UseAuthorization UseRouting UseCors UseEndpoints :

    public void Configure(IApplicationBuilder app)
    {
      ...
    
      app.UseStaticFiles();
    
      app.UseRouting();
      app.UseCors();
    
      app.UseAuthentication();
      app.UseAuthorization();
    
      app.UseEndpoints(endpoints => {
         endpoints.MapControllers();
      });
    
  • Reemplace UseMvc o UseSignalR por UseEndpoints .

  • Si la aplicación usa escenarios de CORS, como , coloque la llamada a antes que cualquier otro middleware que use [EnableCors] UseCors CORS (por ejemplo, coloque antes UseCors de , y UseAuthentication UseAuthorization UseEndpoints ).

  • Reemplace IHostingEnvironment por y agregue una instrucción para el espacio de nombres IWebHostEnvironment using Microsoft.Extensions.Hosting .

  • Reemplace IApplicationLifetime por ( espacio de nombres IHostApplicationLifetime Microsoft.Extensions.Hosting ).

  • Reemplace EnvironmentName por ( espacio de nombres Environments Microsoft.Extensions.Hosting ).

El código siguiente es un ejemplo de Startup.Configure en una aplicación ASP.NET Core 2.2:

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseStaticFiles();

    app.UseAuthentication();

    app.UseSignalR(hubs =>
    {
        hubs.MapHub<ChatHub>("/chat");
    });

    app.UseMvc(routes =>
    {
        routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
    });
}

Después de actualizar el código Startup.Configure anterior:

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseStaticFiles();

    app.UseRouting();

    app.UseCors();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapHub<ChatHub>("/chat");
        endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");
    });
}

Advertencia

Para la mayoría de las aplicaciones, las llamadas a , y deben UseAuthentication aparecer entre las llamadas a y para que sean UseAuthorization UseCors UseRouting UseEndpoints eficaces.

Comprobaciones de estado

Las comprobaciones de estado utilizan el enrutamiento de puntos de conexión con el host genérico. En Startup.Configure, llame a MapHealthChecks en el generador de puntos de conexiones con la dirección URL del punto de conexión o la ruta de acceso relativa:

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health");
});

Los puntos de conexión de las comprobaciones de estado pueden:

  • Especificar uno o más hosts o puertos permitidos.
  • Requerir autorización.
  • Requerir CORS.

Para más información, consulte Comprobaciones de estado en ASP.NET Core.

Guía de middleware de seguridad

La compatibilidad con la autorización y CORS se unifica en torno al enfoque de middleware. Esto permite el uso del mismo middleware y funcionalidad en estos escenarios. En esta versión se proporciona un middleware de autorización actualizado y se ha mejorado el middleware cors para que pueda comprender los atributos usados por los controladores mvc.

CORS

Anteriormente, CORS podía ser difícil de configurar. Se proporcionó middleware para su uso en algunos casos de uso, pero los filtros MVC estaban diseñados para usarse sin el middleware en otros casos de uso. Con ASP.NET Core 3.0, se recomienda que todas las aplicaciones que requieren CORS usen el middleware cors junto con el enrutamiento de puntos de conexión. UseCors se puede proporcionar una directiva predeterminada y los atributos y se pueden usar [EnableCors] para invalidar la directiva predeterminada cuando sea [DisableCors] necesario.

En el ejemplo siguiente:

  • CORS está habilitado para todos los puntos de conexión con la default directiva con nombre.
  • La MyController clase deshabilita CORS con el atributo [DisableCors] .
public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

    app.UseCors("default");

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapDefaultControllerRoute();
    });
}

[DisableCors]
public class MyController : ControllerBase
{
    ...
}

Autorización

En versiones anteriores de ASP.NET Core, la compatibilidad con la autorización se proporcionaba a través del [Authorize] atributo . El middleware de autorización no estaba disponible. En ASP.NET Core 3.0, se requiere middleware de autorización. Se recomienda colocar el middleware ASP.NET Core autorización ( UseAuthorization ) inmediatamente después de UseAuthentication . El middleware de autorización también se puede configurar con una directiva predeterminada, que se puede invalidar.

En ASP.NET Core 3.0 o posterior, se llama a en y lo siguiente UseAuthorization requiere un usuario que haya iniciado Startup.Configure HomeController sesión:

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapDefaultControllerRoute();
    });
}

public class HomeController : Controller
{
    [Authorize]
    public IActionResult BuyWidgets()
    {
        ...
    }
}

Al usar el enrutamiento de puntos de conexión, se recomienda no configurar y, en su lugar, confiar AuthorizeFilter en el middleware de autorización. Si la aplicación usa como filtro global en MVC, se recomienda refactorizar el código para proporcionar una directiva AuthorizeFilter en la llamada a AddAuthorization .

está DefaultPolicy configurado inicialmente para requerir autenticación, por lo que no se requiere ninguna configuración adicional. En el ejemplo siguiente, los puntos de conexión mvc se marcan como para que todas las solicitudes RequireAuthorization se deban autorizar en función de DefaultPolicy . Sin embargo, HomeController permite el acceso sin que el usuario inicie sesión en la aplicación debido a [AllowAnonymous] :

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapDefaultControllerRoute().RequireAuthorization();
    });
}

[AllowAnonymous]
public class HomeController : Controller
{
    ...
}

Autorización para puntos de conexión específicos

La autorización también se puede configurar para clases específicas de puntos de conexión. El código siguiente es un ejemplo de conversión de una aplicación MVC que configuró una aplicación global en una aplicación con una directiva AuthorizeFilter específica que requiere autorización:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    static readonly string _RequireAuthenticatedUserPolicy = 
                            "RequireAuthenticatedUserPolicy";
    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));
        services.AddDefaultIdentity<IdentityUser>(
                 options => options.SignIn.RequireConfirmedAccount = true)
            .AddEntityFrameworkStores<ApplicationDbContext>();

        // Pre 3.0:
        // services.AddMvc(options => options.Filters.Add(new AuthorizeFilter(...));

        services.AddControllersWithViews();
        services.AddRazorPages();
        services.AddAuthorization(o => o.AddPolicy(_RequireAuthenticatedUserPolicy,
                        builder => builder.RequireAuthenticatedUser()));

    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }
        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapDefaultControllerRoute()
                .RequireAuthorization(_RequireAuthenticatedUserPolicy);
            endpoints.MapRazorPages();
        });
    }
}

Las directivas también se pueden personalizar. está DefaultPolicy configurado para requerir autenticación:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));
        services.AddDefaultIdentity<IdentityUser>(
                 options => options.SignIn.RequireConfirmedAccount = true)
            .AddEntityFrameworkStores<ApplicationDbContext>();

        services.AddControllersWithViews();
        services.AddRazorPages();
        services.AddAuthorization(options =>
        {
            options.DefaultPolicy = new AuthorizationPolicyBuilder()
              .RequireAuthenticatedUser()
              .Build();
        });

    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }
        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapDefaultControllerRoute().RequireAuthorization();
            endpoints.MapRazorPages();
        });
    }
}
[AllowAnonymous]
public class HomeController : Controller
{

Como alternativa, todos los puntos de conexión se pueden configurar para requerir autorización sin [Authorize] o mediante la configuración de RequireAuthorization FallbackPolicy . es FallbackPolicy diferente de DefaultPolicy . o DefaultPolicy desencadena , mientras que se desencadena cuando no se establece ninguna otra [Authorize] RequireAuthorization FallbackPolicy directiva. FallbackPolicy está configurado inicialmente para permitir solicitudes sin autorización.

El ejemplo siguiente es el mismo que el ejemplo anterior, pero usa para requerir siempre la autenticación en todos los puntos de conexión, excepto DefaultPolicy FallbackPolicy cuando se especifica [AllowAnonymous] :

public void ConfigureServices(IServiceCollection services)
{
    ...

    services.AddAuthorization(options =>
    {
        options.FallbackPolicy = new AuthorizationPolicyBuilder()
          .RequireAuthenticatedUser()
          .Build();
    });
}

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapDefaultControllerRoute();
    });
}

[AllowAnonymous]
public class HomeController : Controller
{
    ...
}

La autorización por middleware funciona sin que el marco tenga ningún conocimiento específico de la autorización. Por ejemplo, las comprobaciones de estado no tienen ningún conocimiento específico de la autorización, pero las comprobaciones de estado pueden tener una directiva de autorización configurable aplicada por el middleware.

Además, cada punto de conexión puede personalizar sus requisitos de autorización. En el ejemplo siguiente, procesa la autorización con , pero el punto de UseAuthorization conexión de comprobación de estado requiere un DefaultPolicy /healthz admin usuario:

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints
            .MapHealthChecks("/healthz")
            .RequireAuthorization(new AuthorizeAttribute(){ Roles = "admin", });
    });
}

La protección se implementa en algunos escenarios. El middleware de puntos de conexión produce una excepción si se omite una directiva de CORS o autorización debido a la falta de middleware. La compatibilidad del analizador para proporcionar comentarios adicionales sobre la configuración incorrecta está en curso.

Controladores de autorización personalizados

Si la aplicación usa controladores de autorización personalizados,el enrutamiento de puntos de conexión pasa un tipo de recurso diferente a los controladores que MVC. Los controladores que esperan que el recurso de contexto del controlador de autorización sea de tipo (el tipo de recurso proporcionado por los filtros AuthorizationFilterContext DE MVC)tendrán que actualizarse para controlar los recursos de tipo (el tipo de recurso proporcionado a los controladores de autorización por enrutamiento de punto de RouteEndpoint conexión).

MVC todavía usa recursos, por lo que si la aplicación usa filtros de autorización mvc junto con la autorización de enrutamiento de puntos de conexión, puede que sea necesario controlar AuthorizationFilterContext ambos tipos de recursos.

SignalR

La SignalR asignación de centros ahora tiene lugar dentro de UseEndpoints .

Asigne cada centro con MapHub . Al igual que en versiones anteriores, cada centro se muestra explícitamente.

En el ejemplo siguiente, se agrega compatibilidad con ChatHub SignalR el centro:

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapHub<ChatHub>();
    });
}

Hay una nueva opción para controlar los límites de tamaño de los mensajes de los clientes. Por ejemplo, en Startup.ConfigureServices:

services.AddSignalR(hubOptions =>
{
    hubOptions.MaximumReceiveMessageSize = 32768;
});

En ASP.NET Core 2.2, podría establecer y TransportMaxBufferSize que controlaría eficazmente el tamaño máximo del mensaje. En ASP.NET Core 3.0, esa opción ahora solo controla el tamaño máximo antes de observar la contrapresión.

Controladores MVC

La asignación de controladores ahora tiene lugar dentro de UseEndpoints .

Agregue MapControllers si la aplicación usa el enrutamiento de atributos. Puesto que el enrutamiento incluye compatibilidad con muchos marcos en ASP.NET Core 3.0 o posterior, la adición de controladores enrutados a atributos es opcional.

Reemplace lo siguiente:

  • MapRoute con MapControllerRoute
  • MapAreaRoute con MapAreaControllerRoute

Dado que el enrutamiento ahora incluye compatibilidad con algo más que MVC, la terminología ha cambiado para que estos métodos den claramente lo que hacen. Las rutas MapControllerRoute / MapAreaControllerRoute / MapDefaultControllerRoute convencionales, como , se aplican en el orden en que se agregan. Coloque primero rutas más específicas (por ejemplo, rutas para un área).

En el ejemplo siguiente:

  • MapControllers agrega compatibilidad con controladores enrutados por atributos.
  • MapAreaControllerRoute agrega una ruta convencional para los controladores de un área.
  • MapControllerRoute agrega una ruta convencional para los controladores.
public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
        endpoints.MapAreaControllerRoute(
            "admin",
            "admin",
            "Admin/{controller=Home}/{action=Index}/{id?}");
        endpoints.MapControllerRoute(
            "default", "{controller=Home}/{action=Index}/{id?}");
    });
}

Eliminación de sufijos asincrónicos de los nombres de acción del controlador

En ASP.NET Core 3.0, ASP.NET Core MVC quita el sufijo de Async los nombres de acción del controlador. Tanto el enrutamiento como la generación de vínculos se verán afectados por este nuevo valor predeterminado. Por ejemplo:

public class ProductsController : Controller
{
    public async Task<IActionResult> ListAsync()
    {
        var model = await _dbContext.Products.ToListAsync();
        return View(model);
    }
}

Antes de ASP.NET Core 3.0:

  • Se puede acceder a la acción anterior en la ruta Products/ListAsync.

  • Se requiere la generación de vínculos especificando el Async sufijo . Por ejemplo:

    <a asp-controller="Products" asp-action="ListAsync">List</a>
    

En ASP.NET Core 3.0:

  • Se puede acceder a la acción anterior en la ruta Products/List.

  • La generación de vínculos no requiere especificar el Async sufijo . Por ejemplo:

    <a asp-controller="Products" asp-action="List">List</a>
    

Este cambio no afecta a los nombres especificados mediante el [ActionName] atributo . El comportamiento predeterminado se puede deshabilitar con el código siguiente en Startup.ConfigureServices :

services.AddMvc(options =>
    options.SuppressAsyncSuffixInActionNames = false);

Como se explica en la documentación sobrelas diferencias con respecto a versiones anteriores del enrutamiento, hay algunas diferencias en la generación de vínculos (por ejemplo, mediante y API Url.Link similares). Entre ellas se incluyen las siguientes:

  • De forma predeterminada, cuando se usa el enrutamiento de puntos de conexión, no se conservan necesariamente las mayúsculas y minúsculas de los parámetros de ruta en los URI generados. Este comportamiento se puede controlar con la IOutboundParameterTransformer interfaz .
  • La generación de un URI para una ruta no válida (un controlador, una acción o una página que no existe) generará una cadena vacía en el enrutamiento del punto de conexión en lugar de generar un URI no válido.
  • Los valores ambiente (parámetros de ruta del contexto actual) no se usan automáticamente en la generación de vínculos con enrutamiento de punto de conexión. Anteriormente, al generar un vínculo a otra acción (o página), los valores de ruta no especificados se inferían de los valores de ambiente de las rutas actuales. Al usar el enrutamiento de punto de conexión, todos los parámetros de ruta deben especificarse explícitamente durante la generación de vínculos.

Razor Pages

La Razor asignación de páginas ahora tiene lugar dentro de UseEndpoints .

Agregue MapRazorPages si la aplicación usa Razor Pages. Puesto que El enrutamiento de puntos de conexión incluye compatibilidad con muchos marcos, Razor agregar Pages ahora es la opción de participar.

En el método Startup.Configure siguiente, MapRazorPages agrega compatibilidad con Razor Pages:

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

Uso de MVC sin enrutamiento de puntos de conexión

El uso de MVC UseMvc UseMvcWithDefaultRoute mediante o ASP.NET Core 3.0 requiere una suscripción explícita dentro de Startup.ConfigureServices . Esto es necesario porque MVC debe saber si puede confiar en la autorización y el middleware de CORS durante la inicialización. Se proporciona un analizador que advierte si la aplicación intenta usar una configuración no compatible.

Si la aplicación requiere compatibilidad IRouter heredada, deshabilite el EnableEndpointRouting uso de cualquiera de los enfoques siguientes en Startup.ConfigureServices :

services.AddMvc(options => options.EnableEndpointRouting = false);
services.AddControllers(options => options.EnableEndpointRouting = false);
services.AddControllersWithViews(options => options.EnableEndpointRouting = false);
services.AddRazorPages().AddMvcOptions(options => options.EnableEndpointRouting = false);

Comprobaciones de estado

Las comprobaciones de estado se pueden usar como un enrutador-ware con el enrutamiento de puntos de conexión.

Agregue para MapHealthChecks usar comprobaciones de estado con El enrutamiento de puntos de conexión. El MapHealthChecks método acepta argumentos similares a UseHealthChecks . La ventaja de usar over es la capacidad de aplicar la autorización y de tener un mayor control preciso MapHealthChecks sobre la directiva de UseHealthChecks coincidencia.

En el ejemplo siguiente, se MapHealthChecks llama a para un punto de conexión de comprobación de estado en /healthz :

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapHealthChecks("/healthz", new HealthCheckOptions() { });
    });
}

HostBuilder reemplaza a WebHostBuilder

Las ASP.NET Core 3.0 usan el host genérico. Las versiones anteriores usaban el host web. En el código siguiente se muestra ASP.NET Core clase generada por la plantilla 3.0: Program

// requires using Microsoft.AspNetCore.Hosting;
// requires using Microsoft.Extensions.Hosting;

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

En el código siguiente se muestra ASP.NET Core clase generada por plantilla 2.2: Program

public class Program
{
    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
}

IWebHostBuilder permanece en la versión 3.0 y es el tipo de que webBuilder se ve en el ejemplo de código anterior. WebHostBuilder dejará de usarse en una versión futura y se reemplazará por HostBuilder .

El cambio más significativo de WebHostBuilder a es en la HostBuilder inserción de dependencias (DI). Al usar HostBuilder , solo puede insertar lo siguiente en el constructor de Startup :

Las HostBuilder restricciones de DI:

  • Habilite el contenedor de DI para que se pueda crear una sola vez.
  • Evita los problemas de duración del objeto resultantes, como la resolución de varias instancias de singletons.

Para obtener más información, vea Evitar la inserción del servicio de inicio en ASP.NET Core 3.

AddAuthorization se ha movido a un ensamblado diferente

Los ASP.NET Core 2.2 y los AddAuthorization métodos inferiores enMicrosoft.AspNetCore.Authorization.dll:

  • Se ha cambiado el nombre AddAuthorizationCore de .
  • Se han movido a Microsoft.AspNetCore.Authorization.Policy.dll.

Las aplicaciones que usan Microsoft.AspNetCore.Authorization.dll y Microsoft.AspNetCore.Authorization.Policy.dll no se verán afectadas.

Las aplicaciones que no usanMicrosoft.AspNetCore.Authorization.Policy.dll deben realizar una de las siguientes acciones:

  • Agregue una referencia a Microsoft.AspNetCore.Authorization.Policy.dll. Este enfoque funciona para la mayoría de las aplicaciones y es todo lo que se requiere.
  • Cambiar al uso AddAuthorizationCore

Para obtener más información, vea Cambio importante en ) sobrecarga reside en un ensamblado diferente AddAuthorization(o => #386.

IU de Identity

IdentityActualizaciones de la interfaz de ASP.NET Core 3.0:

  • Agregue una referencia de paquete a Microsoft.AspNetCore. Identity . Interfaz de usuario.
  • Las aplicaciones que no usan Razor Pages deben llamar a MapRazorPages . Vea Razor Pages en este documento.
  • Bootstrap 4 es el marco de trabajo de interfaz de usuario predeterminado. Establezca una IdentityUIFrameworkVersion propiedad de proyecto para cambiar el valor predeterminado. Para obtener más información, vea este GitHub anuncio.

SignalR

El SignalR cliente de JavaScript ha cambiado de a @aspnet/signalr @microsoft/signalr . Para reaccionar ante este cambio, cambie las referencias de package.js archivos, require instrucciones e instrucciones ECMAScript. import

System.Text.Json es el protocolo predeterminado

System.Text.Json es ahora el protocolo de concentrador predeterminado que usan el cliente y el servidor.

En Startup.ConfigureServices , llame a para establecer las opciones del AddJsonProtocol serializador.

Servidor:

services.AddSignalR(...)
        .AddJsonProtocol(options =>
        {
            options.PayloadSerializerOptions.WriteIndented = false;
        })

Cliente:

new HubConnectionBuilder()
    .WithUrl("/chathub")
    .AddJsonProtocol(options =>
    {
        options.PayloadSerializerOptions.WriteIndented = false;
    })
    .Build();

Cambie a Newtonsoft.Jsencendido

Si usa características de Newtonsoft.Jsen que no se admiten en System.Text.Jsen, puede volver a Newtonsoft.Json . Vea Usar Newtonsoft.Jsen en un proyecto ASP.NET Core 3.0 SignalR anteriormente en este artículo.

Cachés distribuidas en Redis

El paquete Microsoft.Extensions.Caching.Redis no está disponible para ASP.NET Core 3.0 o versiones posteriores. Reemplace la referencia del paquete por Microsoft.Extensions.Caching.StackExchangeRedis. Para más información, consulte Almacenamiento en caché distribuido en ASP.NET Core.

Participar en la compilación en tiempo de ejecución

Antes de ASP.NET Core 3.0, la compilación en tiempo de ejecución de las vistas era una característica implícita del marco. La compilación en tiempo de ejecución complementa la compilación en tiempo de compilación de vistas. Permite al marco compilar vistas y páginas Razor (archivos .cshtml) cuando se modifican los archivos, sin tener que volver a compilar toda la aplicación. Esta característica admite el escenario de realizar una edición rápida en el IDE y actualizar el explorador para ver los cambios.

En ASP.NET Core 3.0, la compilación en tiempo de ejecución es un escenario de exclusión. La compilación en tiempo de compilación es el único mecanismo para la compilación de vistas que está habilitada de forma predeterminada. El runtime se basa en Visual Studio o dotnet-watch en Visual Studio Code para recompilar el proyecto cuando detecta cambios en los archivos .cshtml. En Visual Studio, los cambios en los archivos .cs, .cshtml o .razor del proyecto que se ejecuta (Ctrl+F5),pero no depurados (F5),desencadenan la recompilación del proyecto.

Para habilitar la compilación en tiempo de ejecución ASP.NET Core proyecto 3.0:

  1. Instale Microsoft.AspNetCore.Mvc. Razor . RuntimeCompilation NuGet paquete.

  2. Actualice Startup.ConfigureServices para llamar a AddRazorRuntimeCompilation :

    Para ASP.NET Core MVC, use el código siguiente:

    services.AddControllersWithViews()
        .AddRazorRuntimeCompilation(...);
    

    Para ASP.NET Core Razor Pages, use el código siguiente:

    services.AddRazorPages()
        .AddRazorRuntimeCompilation(...);
    

El ejemplo de muestra un ejemplo de habilitación condicional de la compilación en tiempo https://github.com/aspnet/samples/tree/main/samples/aspnetcore/mvc/runtimecompilation de ejecución en entornos de desarrollo.

Para obtener más información sobre Razor la compilación de archivos, vea Razorcompilación de archivos en ASP.NET Core .

Migración de bibliotecas a través de varios destinos

Las bibliotecas a menudo necesitan admitir varias versiones de ASP.NET Core. La mayoría de las bibliotecas compiladas con versiones anteriores de ASP.NET Core deben seguir funcionando sin problemas. Las condiciones siguientes requieren que la aplicación se compile de forma cruzada:

  • La biblioteca se basa en una característica que tiene un cambio importante binario.
  • La biblioteca quiere aprovechar las nuevas características de ASP.NET Core 3.0.

Por ejemplo:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFrameworks>netcoreapp3.0;netstandard2.0</TargetFrameworks>
  </PropertyGroup>

  <ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.0'">
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>

  <ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
    <PackageReference Include="Microsoft.AspNetCore" Version="2.1.0" />
  </ItemGroup>
</Project>

Use para habilitar ASP.NET Core API específicas de #ifdefs 3.0:

var webRootFileProvider =
#if NETCOREAPP3_0
    GetRequiredService<IWebHostEnvironment>().WebRootFileProvider;
#elif NETSTANDARD2_0
    GetRequiredService<IHostingEnvironment>().WebRootFileProvider;
#else
#error unknown target framework
#endif

Para obtener más información sobre el uso ASP.NET Core API en una biblioteca de clases, vea Uso de las API de ASP.NET Core en una biblioteca de clases .

Cambios varios

El sistema de validación de .NET Core 3.0 y versiones posteriores trata las propiedades enlazadas o los parámetros que no aceptan valores NULL como si tuvieran un atributo [Required]. Para obtener más información, vea atributo [Obligatorio].

Publicar

Elimine las carpetas bin y obj en el directorio del proyecto.

TestServer

Para las aplicaciones que TestServer usan directamente con el host genérico, cree en TestServer en IWebHostBuilder ConfigureWebHost :

[Fact]
public async Task GenericCreateAndStartHost_GetTestServer()
{
    using var host = await new HostBuilder()
        .ConfigureWebHost(webBuilder =>
        {
            webBuilder
                .UseTestServer()
                .Configure(app => { });
        })
    .StartAsync();

    var response = await host.GetTestServer().CreateClient().GetAsync("/");

    Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}

Cambios importantes en la API

Revise los cambios importantes:

Enrutamiento de puntos de conexión con el parámetro catch-all

Advertencia

Un parámetro catch-all puede relacionar rutas de forma incorrecta debido a un error en el enrutamiento. Las aplicaciones afectadas por este error tienen las características siguientes:

  • Una ruta catch-all (por ejemplo, {**slug}")
  • La ruta catch-all causa un error al relacionar solicitudes que sí que debería relacionar.
  • Al quitar otras rutas, la ruta catch-all empieza a funcionar.

Para ver casos de ejemplo relacionados con este error, consulte los errores 18677 y 16579 en GitHub.

Se incluye una corrección de participación para este error en el SDK de .NET Core 3.1.301 y versiones posteriores. En el código que hay a continuación se establece un cambio interno que corrige este error:

public static void Main(string[] args)
{
   AppContext.SetSwitch("Microsoft.AspNetCore.Routing.UseCorrectCatchAllBehavior", 
                         true);
   CreateHostBuilder(args).Build().Run();
}
// Remaining code removed for brevity.

.NET Core 3.0 en Azure App Service

La implementación de .NET Core en Azure App Service ha finalizado. .NET Core 3.0 está disponible en todos los Azure App Service de datos.