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 de ASP.NET Core 2.2 existente a ASP.NET Core 3.0. Puede resultar útil crear un nuevo proyecto de ASP.NET Core 3.0 para:
- Comparar con el código de ASP.NET Core 2.2.
- Copiar los cambios pertinentes en el proyecto de ASP.NET Core 3.0.
Requisitos previos
- Visual Studio 2019 con la carga de trabajo ASP.NET y desarrollo web
- SDK de .NET Core 3.0
Actualización de la versión del SDK de .NET Core en global.json
Si la solución se basa en un archivo global.json para que el destino sea una versión específica del SDK de .NET Core, actualice su propiedad version
a la versión 3.0 instalada en la máquina:
{
"sdk": {
"version": "3.0.100"
}
}
Actualización del archivo del proyecto
Actualización de la plataforma de destino
ASP.NET Core 3.0 y las 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 las referencias a paquetes obsoletos
No se produce un gran número de paquetes NuGet para ASP.NET Core 3.0. Estas referencias de paquete deben quitarse del archivo del proyecto. Considere el siguiente archivo del proyecto para una aplicación web de ASP.NET Core 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 del proyecto actualizado para ASP.NET Core 3.0:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
</Project>
El archivo del proyecto de ASP.NET Core 3.0 actualizado:
En
<PropertyGroup>
:- Actualiza el TFM a
netcoreapp3.0
- Quita el elemento
<AspNetCoreHostingModel>
. Para obtener más información, consulte Modelo de hospedaje en proceso en este documento.
- Actualiza el TFM a
En
<ItemGroup>
:- Se ha eliminado
Microsoft.AspNetCore.App
. Para obtener más información, consulte Referencia de marco en este documento. Microsoft.AspNetCore.Razor.Design
se quita y en la siguiente lista de paquetes ya no se genera.
- Se ha eliminado
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.Cookies
- Microsoft.AspNetCore.Authentication.Core
- Microsoft.AspNetCore.Authentication.OAuth
- Microsoft.AspNetCore.Authorization.Policy
- Microsoft.AspNetCore.CookiePolicy
- 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.RazorPages
- Microsoft.AspNetCore.Mvc.TagHelpers
- Microsoft.AspNetCore.Mvc.ViewFeatures
- Microsoft.AspNetCore.Razor
- Microsoft.AspNetCore.Razor.Runtime
- Microsoft.AspNetCore.Razor.Design
- 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.Core
- 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.Core
- Microsoft.AspNetCore.StaticFiles
- Microsoft.AspNetCore.WebSockets
- Microsoft.AspNetCore.WebUtilities
- Microsoft.Net.Http.Headers
Revisar cambios importantes
Referencia de 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 marco compartido Microsoft.AspNetCore.App
. 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 marcoMicrosoft.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 tienen como destino el SDK
Microsoft.NET.Sdk
oMicrosoft.NET.Sdk.Razor
deben agregar un elemento explícitoFrameworkReference
aMicrosoft.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 mediante Docker
Las compilaciones dependientes del marco de las aplicaciones de consola que usan un paquete que depende del marco compartido de ASP.NET Core pueden dar el siguiente error de runtime:
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.App
es el marco compartido que contiene el runtime de ASP.NET Core 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 mediante ASP.NET Core sin incluir copias duplicadas de bibliotecas que están disponibles en el marco compartido. Se trata de un ahorro potencial de hasta 18 MB, pero requiere que el runtime de 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 el archivo runtimeconfig.json
generado durante una compilación o publicación de la aplicación. El siguiente archivo JSON muestra una dependencia en el marco compartido de ASP.NET Core:
{
"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 eliminados
ASP.NET Core 3.0 quita algunos ensamblados que anteriormente formaban parte de la referencia del paquete Microsoft.AspNetCore.App
. 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:
Para seguir usando las características proporcionadas por los ensamblados quitados, haga referencia a las versiones 3.0 de los paquetes correspondientes:
Una aplicación web generada por plantillas con Cuentas de usuario individuales requiere agregar los siguientes paquetes:
<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>netcoreapp3.0</TargetFramework> <UserSecretsId>My-secret</UserSecretsId> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="3.0.0" /> <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.0.0" /> <PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="3.0.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.0.0" /> </ItemGroup> </Project>
-
Para obtener más información sobre cómo hacer referencia al paquete específico del proveedor de base de datos, consulte Proveedores de bases de datos.
IU de Identity
Se puede agregar compatibilidad con la interfaz de usuarioIdentity haciendo referencia al paquete Microsoft.AspNetCore.Identity.UI.
Servicios SPA
Autenticación: la compatibilidad con flujos de autenticación de terceros está disponible como paquetes NuGet:
- OAuth de Facebook (Microsoft.AspNetCore.Authentication.Facebook)
- OAuth de Google (Microsoft.AspNetCore.Authentication.Google)
- Autenticación de la cuenta Microsoft (Microsoft.AspNetCore.Authentication.MicrosoftAccount)
- Autenticación de OpenID Connect (Microsoft.AspNetCore.Authentication.OpenIdConnect)
- Token de portador de OpenID Connect (Microsoft.AspNetCore.Authentication.JwtBearer)
- OAuth de Twitter (Microsoft.AspNetCore.Authentication.Twitter)
- Autenticación de WsFederation (Microsoft.AspNetCore.Authentication.WsFederation)
Compatibilidad con la negociación de formato y contenido para
System.Net.HttpClient
: el paquete NuGet Microsoft.AspNet.WebApi.Client proporciona extensibilidad útil aSystem.Net.HttpClient
con algunas API comoReadAsAsync
yPostJsonAsync
. Sin embargo, este paquete depende deNewtonsoft.Json
, no deSystem.Text.Json
. Esto significa, por ejemplo, que se omiten los nombres de propiedad de serialización especificados porJsonPropertyNameAttribute
(System.Text.Json
). Hay un paquete NuGet más reciente que contiene métodos de extensión similares, pero usaSystem.Text.Json
: System.Net.Http.Json.Compilación en tiempo de ejecución Razor: la compatibilidad con la compilación en tiempo de ejecución de las vistas y páginas de Razor ahora forma parte de Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation.
Compatibilidad con MVC
Newtonsoft.Json
(Json.NET): la compatibilidad con el uso de MVC conNewtonsoft.Json
ahora forma parte deMicrosoft.AspNetCore.Mvc.NewtonsoftJson
.
Cambios de inicio
En la imagen siguiente se muestran las líneas eliminadas y modificadas en una aplicación web de Páginas Razor de ASP.NET Core 2.2:
En la imagen anterior, el código eliminado se muestra en rojo. El código eliminado no muestra el código de opciones cookie, que se eliminó antes de comparar los archivos.
En la imagen siguiente se muestran las líneas agregadas y modificadas en una aplicación web de Páginas Razor de ASP.NET Core 3.0:
En la imagen anterior, el código agregado se muestra en verde. Para obtener información sobre los siguientes cambios:
services.AddMvc
paraservices.AddRazorPages
, consulta el registro del servicio MVC en este documento.CompatibilityVersion
, consulta Versión de compatibilidad para ASP.NET Core MVC.IHostingEnvironment
paraIWebHostEnvironment
, consulta este anuncio de GitHub.app.UseAuthorization
se agregó a las plantillas para mostrar el middleware de autorización de pedidos que se debe agregar. Si la aplicación no usa la autorización, puedes quitar de forma segura la llamada aapp.UseAuthorization
.app.UseEndpoints
, consulta Páginas Razor o Migrar Startup.Configure en este documento.
Compatibilidad con analizadores
Proyectos que tienen como destino analizadores Microsoft.NET.Sdk.Web
de referencia implícitamente enviados anteriormente como parte del paquete Microsoft.AspNetCore.Mvc.Analyzers. No se requieren referencias adicionales para habilitarlas.
Si la aplicación usa analizadores de API enviados anteriormente mediante el paquete Microsoft.AspNetCore.Mvc.Api.Analyzers, edita el archivo del proyecto para hacer referencia a los analizadores enviados como parte del SDK web de .NET Core:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<IncludeOpenAPIAnalyzers>true</IncludeOpenAPIAnalyzers>
</PropertyGroup>
...
</Project>
Biblioteca de clases Razor
Los proyectos de la biblioteca de clases Razor que proporcionan componentes de interfaz de usuario para MVC deben establecer la propiedad AddRazorSupportForMvc
en el archivo del proyecto:
<PropertyGroup>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
</PropertyGroup>
Modelo de hospedaje en proceso
Los proyectos tienen como valor predeterminado el modelo de hospedaje dentro del proceso en ASP.NET Core 3.0 o versiones posteriores. De manera opcional, puedes quitar la propiedad <AspNetCoreHostingModel>
en el archivo del proyecto si su valor es InProcess
.
Kestrel
Configuración
Migra la configuración Kestrel al generador de hosts 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 ConfigureWebHost
en lugar de ConfigureWebHostDefaults
, llame a UseKestrel
en el generador de hosts 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();
}
El middleware de conexión reemplaza a los adaptadores de conexión
Los adaptadores de conexión (Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal.IConnectionAdapter
) se han quitado de Kestrel. Reemplaza los adaptadores de conexión por middleware de conexión. El middleware de conexión es similar al middleware HTTP en la canalización de ASP.NET Core, pero para conexiones de nivel inferior. Registro de conexiones y HTTPS:
- Se han movido de adaptadores de conexión al 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, consulta el ejemplo TlsFilterConnectionHandler en la sección ListenOptions.Protocols del Kestrel artículo.
Las abstracciones de transporte se han quitado y se han hecho públicas
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 los tipos asociados se han quitado.- NoDelay se movió 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, consulta los siguientes recursos de GitHub:
- Abstracciones de red de cliente/servidor (dotnet/AspNetCore #10308)
- Implemente la nueva abstracción del cliente de escucha de bedrock y vuelva a plat Kestrel en la parte superior (dotnet/AspNetCore #10321)
Encabezados de solicitud de finalizador Kestrel
En el caso de 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 los encabezados y los finalizadores, por lo que los finalizadores se han movido a una nueva colección (RequestTrailerExtensions
) en 3.0.
Los finalizadores de solicitudes HTTP/2 son:
- No está disponible en ASP.NET Core 2.2.
- Disponible en 3.0 como
RequestTrailerExtensions
.
Hay métodos nuevos de extensión de solicitud para tener acceso a estos finalizadores. Al igual que con HTTP/1.1, los finalizadores están disponibles después de leer el cuerpo de la solicitud hasta el final.
Para la versión 3.0, están disponibles los siguientes métodos RequestTrailerExtensions
:
GetDeclaredTrailers
: obtiene el encabezadoTrailer
de solicitud que muestra 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 su lectura. Esta comprobación no supone que hay finalizadores que se van a leer. Es posible que no haya finalizadores para leer incluso si este método devuelvetrue
.GetTrailer
: obtiene el encabezado de finalización solicitado de la respuesta. CompruebeSupportsTrailers
antes de llamar aGetTrailer
, o se puede producir NotSupportedException si la solicitud no admite encabezados finales.
Para obtener más información, consulte Colocar los finalizadores de solicitud en una colección por separado (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 una fuente común de ausencia de subprocesos que provocan bloqueos en la aplicación. En la versión 3.0, AllowSynchronousIO
se ha deshabilitado de manera predeterminada. Para obtener más información, consulte la sección sobre E/S sincrónica del Kestrel artículo.
Si se necesita E/S sincrónica, se puede habilitar configurando la opción AllowSynchronousIO
en el servidor que se usa (por ejemplo, al llamar a ConfigureKestrel
si se usa Kestrel). Tenga en cuenta que los servidores (Kestrel, HttpSys, TestServer, etc.) tienen su propia opción AllowSynchronousIO
que no afectará a otros servidores. La E/S sincrónica se puede habilitar para todos los servidores por solicitud mediante la opción IHttpBodyControlFeature.AllowSynchronousIO
:
var syncIOFeature = HttpContext.Features.Get<IHttpBodyControlFeature>();
if (syncIOFeature != null)
{
syncIOFeature.AllowSynchronousIO = true;
}
Si tiene problemas con las implementaciones TextWriter u otras secuencias que llaman a API sincrónicas en Dispose, llame a la nueva API DisposeAsync en su lugar.
Para obtener más información, consulte [Anuncio] AllowSynchronousIO deshabilitado en todos los servidores (dotnet/AspNetCore #7644).
Almacenamiento en búfer del formateador de salida
Los formateadores de salida basados en Newtonsoft.Json, XmlSerializery DataContractSerializer 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, el formateador basado en System.Text.Json
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 configurar SuppressOutputFormatterBuffering en su inicio:
services.AddControllers(options => options.SuppressOutputFormatterBuffering = true)
Tenga en cuenta que esto puede dar lugar a que la aplicación inicie una excepción de runtime si AllowSynchronousIO
no está también configurado.
Ensamblado Microsoft.AspNetCore.Server.Kestrel.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. Este no fue un cambio importante en el uso de los atributos TypeForwardedTo
. Para la versión 3.0, el ensamblado Microsoft.AspNetCore.Server.Kestrel.Https.dll vacío y el paquete NuGet se han quitado.
Las bibliotecas que hacen referencia a Microsoft.AspNetCore.Server.Kestrel.Https deben actualizar las dependencias de ASP.NET Core a 2.1 o una versión posterior.
Las aplicaciones y bibliotecas que tienen como destino ASP.NET Core 2.1 o versiones posteriores deben quitar las referencias directas al paquete Microsoft.AspNetCore.Server.Kestrel.Https.
Compatibilidad con Newtonsoft.Json (Json.NET)
Como parte del trabajo para mejorar el marco compartido de ASP.NET Core, Newtonsoft.Json (Json.NET) se ha quitado del marco compartido de ASP.NET Core.
El serializador JSON predeterminado para ASP.NET Core ahora es System.Text.Json, que es nuevo en .NET Core 3.0. Considere la posibilidad de usar System.Text.Json
cuando sea posible. Es de alto rendimiento y no requiere una dependencia de biblioteca adicional. Sin embargo, dado que System.Text.Json
es nuevo, es posible que actualmente falten características que la aplicación necesita. Para obtener más información, consulte Migración desde Newtonsoft.json a System.Text.Json.
Uso de Newtonsoft.Json en un proyecto de SignalR ASP.NET Core 3.0
Instale el paquete NuGet Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson.
En el cliente, encadene una llamada de método
AddNewtonsoftJsonProtocol
a la instanciaHubConnectionBuilder
:new HubConnectionBuilder() .WithUrl("/chathub") .AddNewtonsoftJsonProtocol(...) .Build();
En el servidor, encadene una llamada de método
AddNewtonsoftJsonProtocol
a la llamada de métodoAddSignalR
enStartup.ConfigureServices
:services.AddSignalR() .AddNewtonsoftJsonProtocol(...);
Uso de Newtonsoft.Json en un proyecto de ASP.NET Core 3.0 MVC
Instale el paquete
Microsoft.AspNetCore.Mvc.NewtonsoftJson
.Actualice
Startup.ConfigureServices
para llamar aAddNewtonsoftJson
.services.AddMvc() .AddNewtonsoftJson();
AddNewtonsoftJson
es compatible con los nuevos métodos de registro del servicio MVC:AddRazorPages
AddControllersWithViews
AddControllers
services.AddControllers() .AddNewtonsoftJson();
La configuración
Newtonsoft.Json
se puede establecer en la llamada aAddNewtonsoftJson
:services.AddMvc() .AddNewtonsoftJson(options => options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver());
Nota: Si el método
AddNewtonsoftJson
no está disponible, asegúrese de que instaló el paqueteMicrosoft.AspNetCore.Mvc.NewtonsoftJson
. Un error común es instalar el paquete Newtonsoft.Json en lugar del paqueteMicrosoft.AspNetCore.Mvc.NewtonsoftJson
.
Para obtener más información, consulta Agregar compatibilidad con formato JSON basado en Newtonsoft.Json.
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 en IServiceCollection
. Las plantillas usan estos nuevos métodos en lugar de AddMvc
. Sin embargo, AddMvc
continúa comportándose como lo hacía 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 para 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 Páginas Razor y compatibilidad mínima con controladores. 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 equivale a llamar a AddMvc
en ASP.NET Core 2.2:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddRazorPages();
}
Código de inicio de enrutamiento
Si una aplicación llama a UseMvc
o UseSignalR
, migre la aplicación al enrutamiento de punto de conexión si es posible. Para mejorar la compatibilidad del enrutamiento de punto de conexión 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 experimenta problemas con el enrutamiento de punto de conexión en la versión 2.2, espere mejoras en ASP.NET Core 3.0 con las excepciones siguientes:
- Si la aplicación implementa
IRouter
o hereda deRoute
, use DynamicRouteValuesTransformer como reemplazo. - Si la aplicación accede a
RouteData.Routers
directamente dentro de MVC para analizar direcciones URL, puede reemplazarla por el uso de LinkParser.ParsePathByEndpointName.- Defina la ruta con un nombre de ruta.
- Use
LinkParser.ParsePathByEndpointName
y pase el nombre de ruta deseado.
El enrutamiento de punto de conexión admite la misma sintaxis de patrón de ruta y las características de creación de patrones de ruta que IRouter
. El enrutamiento de punto de conexión admite IRouteConstraint
. El enrutamiento de punto de conexión admite [Route]
, [HttpGet]
y los demás atributos de enrutamiento de MVC.
Para la mayoría de las aplicaciones, solo Startup
requiere cambios.
Migrar Startup.Configure
Consejos generales:
Agregue
UseRouting
.Si la aplicación llama a
UseStaticFiles
, coloqueUseStaticFiles
antes queUseRouting
.Si la aplicación usa características de autenticación y autorización como
AuthorizePage
o[Authorize]
, coloque la llamada aUseAuthentication
yUseAuthorization
: después,UseRouting
yUseCors
, pero antes deUseEndpoints
:public void Configure(IApplicationBuilder app) { ... app.UseStaticFiles(); app.UseRouting(); app.UseCors(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
Reemplace
UseMvc
oUseSignalR
porUseEndpoints
.Si la aplicación usa escenarios CORS, como
[EnableCors]
, coloque la llamada aUseCors
antes de cualquier otro middleware que use CORS (por ejemplo, coloqueUseCors
antes deUseAuthentication
,UseAuthorization
yUseEndpoints
).Reemplace
IHostingEnvironment
porIWebHostEnvironment
y agregue una instrucciónusing
para el espacio de nombres Microsoft.AspNetCore.Hosting.Reemplace
IApplicationLifetime
por IHostApplicationLifetime (espacio de nombres Microsoft.Extensions.Hosting).Reemplace
EnvironmentName
por Environments (espacio de nombres Microsoft.Extensions.Hosting).
El código siguiente es un ejemplo de Startup.Configure
en una aplicación típica de 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 UseAuthentication
, UseAuthorization
y UseCors
deben aparecer entre las llamadas a UseRouting
y UseEndpoints
para que sean 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 obtener 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 mejora el middleware de CORS para que pueda comprender los atributos que usan los controladores MVC.
CORS
Anteriormente, CORS podía ser difícil de configurar. El middleware se proporcionó 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 requieran CORS usen el middleware de CORS junto con el enrutamiento de punto de conexión. Se puede proporcionar UseCors
con una directiva predeterminada, y los atributos [EnableCors]
y [DisableCors]
se pueden usar para invalidar la directiva predeterminada cuando sea necesario.
En el ejemplo siguiente:
- CORS está habilitado para todos los puntos de conexión con la directiva de nombre
default
. - La clase
MyController
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
{
...
}
Authorization
En versiones anteriores de ASP.NET Core, se proporcionó compatibilidad con la autorización a través del atributo [Authorize]
. 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 de autorización de ASP.NET Core (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 versiones posteriores, se llama a UseAuthorization
en Startup.Configure
y el siguiente HomeController
requiere un usuario que haya iniciado 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 punto de conexión, no se recomienda configurar AuthorizeFilter y, en su lugar, se recomienda confiar en el middleware de autorización. Si la aplicación usa AuthorizeFilter
como filtro global en MVC, se recomienda refactorizar el código para proporcionar una directiva en la llamada a AddAuthorization
.
Inicialmente se configura DefaultPolicy
para requerir autenticación, por lo que no se requiere ninguna configuración adicional. En el ejemplo siguiente, los puntos de conexión de MVC se marcan como RequireAuthorization
para que todas las solicitudes 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ó un AuthorizeFilter
global en una aplicación con una directiva 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. DefaultPolicy
está 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 RequireAuthorization
mediante la configuración de FallbackPolicy
. FallbackPolicy
es diferente de DefaultPolicy
. DefaultPolicy
se desencadena mediante [Authorize]
o RequireAuthorization
, mientras que FallbackPolicy
se desencadena cuando no se establece ninguna otra directiva. FallbackPolicy
se configura inicialmente para permitir solicitudes sin autorización.
El ejemplo siguiente es el mismo que el ejemplo DefaultPolicy
anterior, pero usa FallbackPolicy
para requerir siempre la autenticación en todos los puntos de conexión, excepto 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, UseAuthorization
procesa la autorización con DefaultPolicy
, pero el punto de conexión de comprobación de estado /healthz
requiere un usuario admin
:
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 para 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 que falta middleware. La compatibilidad con el analizador para proporcionar comentarios adicionales sobre una configuración incorrecta está en curso.
Controladores de autorización personalizados
Si la aplicación usa controladores de autorización personalizados, el enrutamiento de punto 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 AuthorizationFilterContext (el tipo de recurso proporcionado por los filtros MVC) deberá actualizarse para controlar los recursos de tipo RouteEndpoint (el tipo de recurso proporcionado a los controladores de autorización por el enrutamiento de punto de conexión).
MVC sigue usando recursos AuthorizationFilterContext
, por lo que si la aplicación usa filtros de autorización de MVC junto con la autorización de enrutamiento de puntos de conexión, puede ser necesario controlar ambos tipos de recursos.
SignalR
La asignación de centros SignalR ahora tiene lugar dentro de UseEndpoints
.
Asigne cada centro con MapHub
. Como en versiones anteriores, cada centro aparece explícitamente.
En el ejemplo siguiente, se agrega compatibilidad con el centro ChatHub
SignalR:
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 mensaje de los clientes. Por ejemplo, en Startup.ConfigureServices
:
services.AddSignalR(hubOptions =>
{
hubOptions.MaximumReceiveMessageSize = 32768;
});
En ASP.NET Core 2.2, podría establecer TransportMaxBufferSize
y eso 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 que se observe la contrapresión.
Ensamblados SignalR en el marco compartido
Los ensamblados del lado servidor SignalR de ASP.NET Core ahora están instalados con el SDK de .NET Core. Para obtener más información, consulte Quitar referencias de paquetes obsoletos en esta documentació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. Dado que el enrutamiento incluye compatibilidad con muchos marcos en ASP.NET Core 3.0 o versiones posteriores, agregar controladores enrutados por atributos es opcional.
Reemplace lo siguiente:
MapRoute
conMapControllerRoute
MapAreaRoute
conMapAreaControllerRoute
Dado que el enrutamiento ahora incluye compatibilidad con más que solo MVC, la terminología ha cambiado para hacer que estos métodos indiquen claramente lo que hacen. Las rutas convencionales, como MapControllerRoute
/MapAreaControllerRoute
/MapDefaultControllerRoute
, se aplican en el orden en que se agregan. Coloque primero rutas más específicas (como 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?}");
});
}
Se ha quitado el sufijo Async de los nombres de acción de controlador
En ASP.NET Core 3.0, ASP.NET Core MVC quita el sufijo Async
de los nombres de acción del controlador. Tanto el enrutamiento como la generación de vínculos se ven 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.
La generación de vínculos requiere que se especifique el sufijo
Async
. 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 que se especifique el sufijo
Async
. Por ejemplo:<a asp-controller="Products" asp-action="List">List</a>
Este cambio no afecta a los nombres especificados mediante el atributo [ActionName]
. El comportamiento predeterminado se deshabilita con el siguiente código en Startup.ConfigureServices
:
services.AddMvc(options =>
options.SuppressAsyncSuffixInActionNames = false);
Cambios en la generación de vínculos
Hay algunas diferencias en la generación de vínculos (por ejemplo, el uso de Url.Link
y API similares). Entre ellas se incluyen las siguientes:
- De manera predeterminada, cuando se usa el enrutamiento de punto de conexión, no se conserva necesariamente el uso de mayúsculas y minúsculas en los parámetros de ruta en los URI generados. Este comportamiento se puede controlar con la interfaz
IOutboundParameterTransformer
. - La generación de un URI para una ruta no válida (un controlador/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 ambientales (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 a partir de los valores de ambiente de las rutas actuales. Al usar el enrutamiento de puntos de conexión, se deben especificar explícitamente todos los parámetros de ruta durante la generación de vínculos.
Razor Pages
La asignación de Páginas Razor ahora tiene lugar dentro de UseEndpoints
.
Agregue MapRazorPages
si la aplicación usa Páginas Razor. Dado que el enrutamiento de puntos de conexión incluye compatibilidad con muchos marcos, la adición de Páginas Razor ahora es opcional.
En el método Startup.Configure
siguiente, MapRazorPages
agrega compatibilidad con Páginas Razor:
public void Configure(IApplicationBuilder app)
{
...
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
Uso de MVC sin enrutamiento de punto de conexión
El uso de MVC mediante UseMvc
o UseMvcWithDefaultRoute
en ASP.NET Core 3.0 requiere una participación explícita dentro de Startup.ConfigureServices
. Esto es necesario porque MVC debe saber si puede basarse 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 admitida.
Si la aplicación requiere compatibilidad IRouter
heredada, deshabilite EnableEndpointRouting
mediante 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 mantenimiento
Las comprobaciones de estado se pueden usar como router-ware con enrutamiento de punto de conexión.
Agregue MapHealthChecks
para usar comprobaciones de estado con el enrutamiento de punto de conexión. El método MapHealthChecks
acepta argumentos similares a UseHealthChecks
. La ventaja de usar MapHealthChecks
sobre UseHealthChecks
es la capacidad de aplicar la autorización y tener un mayor control específico sobre la directiva de coincidencias.
En el ejemplo siguiente, se llama a MapHealthChecks
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 plantillas de ASP.NET Core 3.0 usan Generic Host. Las versiones anteriores usaban Web Host. En el código siguiente se muestra la clase Program
generada por la plantilla de ASP.NET Core 3.0:
// 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 la clase Program
generada por la plantilla de ASP.NET Core 2.2:
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 webBuilder
que se muestra en el ejemplo de código anterior. WebHostBuilder quedará en desuso en una versión futura y se reemplazará por HostBuilder
.
El cambio más significativo de WebHostBuilder
a HostBuilder
está en la inserción de dependencias (DI). Al usar HostBuilder
, solo puede insertar lo siguiente en el constructor de Startup
:
Las restricciones de inserción de dependencias HostBuilder
:
- Habilite el contenedor de inserción de dependencias para que se compile solo una vez.
- Evita los problemas de duración de objetos resultantes, como resolver varias instancias de singletons.
Para obtener más información, consulte Evitar la inserción de servicios de inicio en ASP.NET Core 3.
AddAuthorization se ha movido a otro ensamblado
Los métodos AddAuthorization
de ASP.NET Core 2.2 y versiones inferiores en Microsoft.AspNetCore.Authorization.dll:
- Se ha cambiado el nombre
AddAuthorizationCore
. - Se ha movido a Microsoft.AspNetCore.Authorization.Policy.dll.
Las aplicaciones que usan Microsoft.AspNetCore.Authorization.dll y Microsoft.AspNetCore.Authorization.Policy.dll no se ven afectadas.
Las aplicaciones que no usan Microsoft.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.
- Cambie al uso de
AddAuthorizationCore
Para obtener más información, consulte Cambio importante en AddAuthorization(o =>
) sobrecarga que reside en un ensamblado diferente n.º 386.
IU de Identity
La interfaz de usuario Identity se actualiza para ASP.NET Core 3.0:
- Agregue una referencia de paquete a Microsoft.AspNetCore.Identity.UI.
- Las aplicaciones que no usan Páginas Razor deben llamar a
MapRazorPages
. Consulte Páginas Razor en este documento. - Bootstrap 4 es el marco de la interfaz de usuario predeterminado. Establezca una propiedad de proyecto
IdentityUIFrameworkVersion
para cambiar el valor predeterminado. Para obtener más información, consulte este anuncio de GitHub.
SignalR
El cliente de JavaScript SignalR ha cambiado de @aspnet/signalr
a @microsoft/signalr
. Para reaccionar a este cambio, cambie las referencias en los archivos package.json
, las instrucciones require
y las instrucciones import
de ECMAScript.
System.Text.Json es el protocolo predeterminado
System.Text.Json
es ahora el protocolo de centro predeterminado que usa el cliente y el servidor.
En Startup.ConfigureServices
, llame a AddJsonProtocol
para establecer las opciones del serializador.
Server:
services.AddSignalR(...)
.AddJsonProtocol(options =>
{
options.PayloadSerializerOptions.WriteIndented = false;
})
Cliente:
new HubConnectionBuilder()
.WithUrl("/chathub")
.AddJsonProtocol(options =>
{
options.PayloadSerializerOptions.WriteIndented = false;
})
.Build();
Cambiar a Newtonsoft.Json
Si usa características de Newtonsoft.Json que no se admiten en System.Text.Json, puede volver a Newtonsoft.Json
. Consulte Uso de Newtonsoft.Json en un proyecto SignalR de ASP.NET Core 3.0 más atrás en este artículo.
Cachés distribuidas de Redis
El paquete Microsoft.Extensions.Caching.Redis no está disponible para aplicaciones de ASP.NET Core 3.0 o 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.
Participación 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 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 las vistas. Permite al marco compilar vistas y páginas Razor (archivos .cshtml
) cuando se modifican los archivos, sin tener que recompilar 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 participación. La compilación en tiempo de ejecución es el único mecanismo para ver la compilación habilitada de manera 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, cambia a los archivos .cs
, .cshtml
o .razor
del proyecto que se ejecuta (Ctrl+F5), pero no se depura (F5), desencadena la recompilación del proyecto.
Para habilitar la compilación en tiempo de ejecución en el proyecto de ASP.NET Core 3.0:
Instale el paquete NuGet Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation.
Actualice
Startup.ConfigureServices
para llamar aAddRazorRuntimeCompilation
:Para ASP.NET Core MVC, use el código siguiente:
services.AddControllersWithViews() .AddRazorRuntimeCompilation(...);
Para Páginas Razor de ASP.NET Core, use el código siguiente:
services.AddRazorPages() .AddRazorRuntimeCompilation(...);
El ejemplo en https://github.com/aspnet/samples/tree/main/samples/aspnetcore/mvc/runtimecompilation muestra un ejemplo de habilitación condicional de la compilación en tiempo de ejecución en entornos de desarrollo.
Para obtener más información sobre la compilación de archivos Razor, consulteCompilación de archivos Razor en ASP.NET Core.
Migración de bibliotecas a través de varios destinos
Las bibliotecas suelen necesitar admitir varias versiones de ASP.NET Core. La mayoría de las bibliotecas compiladas con versiones anteriores de ASP.NET Core deberían 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 #ifdefs
para habilitar las API específicas de ASP.NET Core 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 de las API de ASP.NET Core en una biblioteca de clases, consulte 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, consulte Atributo [requerido].
Publicar
Elimine las carpetas bin y obj en el directorio del proyecto.
TestServer
En el caso de las aplicaciones que usan TestServer directamente con el host genérico, cree TestServer
en IWebHostBuilder en 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:
- Lista completa de cambios importantes en la versión de ASP.NET Core 3.0
- Cambios importantes en la API en Antiforgery, CORS, Diagnostics, MVC y Routing. Esta lista incluye cambios importantes para los modificadores de compatibilidad.
- Para obtener un resumen de los cambios importantes de 2.2 a 3.0 en .NET Core, ASP.NET Core y Entity Framework Core, consulte Cambios importantes para la migración de la versión 2.2 a la 3.0.
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
El lanzamiento de .NET Core en Azure App Service ha finalizado. .NET Core 3.0 está disponible en todos los centros de datos de Azure App Service.
Módulo de ASP.NET Core (ANCM)
Si el módulo de ASP.NET Core (ANCM) no era un componente seleccionado cuando Visual Studio se instaló o si se instaló una versión anterior de ANCM en el sistema, descargue el instalador de agrupación de hospedaje de .NET Core más reciente (descarga directa) y ejecute el instalador. Para obtener más información, consulte Agrupación de hospedaje.