Novedades de ASP.NET Core 6.0
En este artículo se resaltan los cambios más importantes de ASP.NET Core 6.0, con vínculos a la documentación pertinente.
Mejoras en ASP.NET Core MVC y Razor
API mínimas
Las API mínimas están diseñadas para crear API HTTP con dependencias mínimas. Son ideales para microservicios y aplicaciones que desean incluir solo los archivos, las características y las dependencias mínimas en ASP.NET Core. Para más información, consulte:
- Tutorial: Creación de una API mínima con ASP.NET Core
- Diferencias entre las API mínimas y las API con controladores
- Referencia rápida de las API mínimas
- Ejemplos de código migrados al nuevo modelo de hospedaje mínimo en 6.0
SignalR
Etiqueta de actividad de larga duración para conexiones SignalR
SignalR usa la nueva Microsoft.AspNetCore.Http.Features.IHttpActivityFeature.Activity para agregar una etiqueta http.long_running
a la actividad de solicitud. Los servicios de APM, como Application Insights de Azure Monitor, usan IHttpActivityFeature.Activity
para filtrar las solicitudes de SignalR de la creación de alertas de solicitud de larga duración.
Mejoras en el rendimiento de SignalR
- Asigne HubCallerClients una vez por conexión en lugar de hacerlo una vez por cada llamada de método del centro.
- Evite la asignación de clausura en SignalR
DefaultHubDispatcher.Invoke
. El estado se pasa a una función estática local a través de parámetros a fin de evitar una asignación de clausura. Para más información, consulte esta solicitud de incorporación de cambios de GitHub. - Asigne un StreamItemMessage único por secuencia en vez de hacerlo por elemento de secuencia en el streaming de servidor a cliente. Para más información, consulte esta solicitud de incorporación de cambios de GitHub.
Compilador de Razor
El compilador de Razor se actualizó para usar generadores de código fuente
El compilador de Razor ahora se basa en generadores de código fuente de C#. Los generadores de código fuente se ejecutan durante la compilación e inspeccionan lo que se compila a fin de generar archivos adicionales que se compilan junto con el rest del proyecto. El uso de generadores de código fuente simplifica el compilador de Razor y acelera considerablemente los tiempos de compilación.
El compilador de Razor ya no genera un ensamblado de Vistas independiente
Anteriormente, el compilador de Razor utilizaba un proceso de compilación de dos pasos que generaba un ensamblado de Vistas independiente que contenía las vistas y páginas generadas (archivos .cshtml
) definidas en la aplicación. Los tipos generados eran públicos y estaban en el espacio de nombres AspNetCore
.
El compilador de Razor actualizado genera los tipos de vistas y páginas en el ensamblado principal del proyecto. Estos tipos ahora se generan de manera predeterminada como sellados internamente en el espacio de nombres AspNetCoreGeneratedDocument
. Este cambio mejora el rendimiento de la compilación, activa la implementación de un archivo único y permite que estos tipos participen en la Recarga activa.
Para más información sobre este cambio, consulte el problema de anuncio relacionado en GitHub.
Mejoras en las API y el rendimiento de ASP.NET Core
Se hicieron muchos cambios para reducir las asignaciones y mejorar el rendimiento en toda la pila:
- Método de extensión app. Use sin asignación. La sobrecarga nueva de
app.Use
requiere pasar el contexto anext
, lo que guarda dos asignaciones internas por solicitud que son necesarias cuando se usa la otra sobrecarga. - Se han reducido las asignaciones de memoria al acceder a HttpRequest.Cookies. Para más información, consulte este problema de GitHub.
- Use LoggerMessage.Define para el servidor web HTTP.sys solo de Windows. Las llamadas a
LoggerMessage.Define
reemplazaron a las llamadas de método de extensión ILogger. - Reduzca aproximadamente el 30 % la sobrecarga por conexión en SocketConnection. Para más información, consulte esta solicitud de incorporación de cambios de GitHub.
- Reduzca las asignaciones mediante la eliminación de delegados de registro en tipos genéricos. Para más información, consulte esta solicitud de incorporación de cambios de GitHub.
- Acceso GET más rápido (alrededor de un 50 %) a las características de uso frecuente, como IHttpRequestFeature, IHttpResponseFeature, IHttpResponseBodyFeature, IRouteValuesFeature y IEndpointFeature. Para más información, consulte esta solicitud de incorporación de cambios de GitHub.
- Use cadenas de instancia única para nombres de encabezado conocidos, incluso si no están en el bloque del encabezado conservado. Usar una cadena de instancia única permite evitar la presencia de varios duplicados de la misma cadena en conexiones de larga duración, como en Microsoft.AspNetCore.WebSockets. Para más información, consulte este problema de GitHub.
- Reutilice HttpProtocol CancellationTokenSource en Kestrel. Use el método CancellationTokenSource.TryReset nuevo en
CancellationTokenSource
para reutilizar los tokens si no se han cancelado. Para más información, consulte este problema de GitHub y vea este vídeo. - Implementa y usa un objeto AdaptiveCapacityDictionary en Microsoft.AspNetCore.HttpRequestCookieCollection para un acceso más eficaz a los diccionarios. Para más información, consulte esta solicitud de incorporación de cambios de GitHub.
Se redujo la superficie de memoria para conexiones TLS inactivas
Para las conexiones TLS de larga duración en las que los datos solo se envían ocasionalmente de un lado a otro, redujimos considerablemente la superficie de memoria de las aplicaciones ASP.NET Core en .NET 6. Esto debería permitir mejorar la escalabilidad de escenarios como los servidores WebSocket. Esto fue posible debido a numerosas mejoras en System.IO.Pipelines, SslStream y Kestrel. En las secciones siguientes se detallan algunas de las mejoras que contribuyeron a reducir la superficie de memoria:
Reducción del tamaño de System.IO.Pipelines.Pipe
Para cada conexión establecida, se asignan dos canalizaciones en Kestrel:
- La capa de transporte a la capa de aplicación para la solicitud.
- La capa de aplicación a la capa de transporte para la respuesta.
Al disminuir el tamaño de System.IO.Pipelines.Pipe de 368 bytes a 264 bytes (una reducción aproximada del 28,2 %), se ahorran 208 bytes por conexión (104 bytes por canalización).
Agrupación de SocketSender
Los objetos SocketSender
(de la subclase SocketAsyncEventArgs) tienen unos 350 bytes en tiempo de ejecución. En lugar de asignar un objeto SocketSender
nuevo por conexión, se pueden agrupar. Los objetos SocketSender
se pueden agrupar porque los envíos suelen ser muy rápidos. Agruparlos reduce la sobrecarga por conexión. En lugar de asignar 350 bytes por conexión, solo se asignan 350 bytes por IOQueue
. Para evitar la contención, la asignación se hace por cola. Nuestro servidor WebSocket con 5000 conexiones inactivas pasó de asignar alrededor de 1,75 MB (350 bytes * 5000) a asignar alrededor de 2,8 KB (350 bytes * 8) para los objetos SocketSender
.
Lecturas de cero bytes con SslStream
Las lecturas sin búfer son una técnica que se emplea en ASP.NET Core para evitar alquilar memoria del grupo de memoria si no hay datos disponibles en el socket. Antes de esta modificación, el servidor WebSocket con 5000 conexiones inactivas requería alrededor de 200 MB sin TLS, en comparación con alrededor de 800 MB con TLS. Algunas de estas asignaciones (4000 por conexión) provenían de que Kestrel tenía que mantener un búfer ArrayPool<T> mientras se esperaba que se completaran las lecturas en SslStream. Dado que estas conexiones estaban inactivas, ninguna de las lecturas se completó ni volvió su búfer a ArrayPool
, lo que obligaba a ArrayPool
a asignar más memoria. Las asignaciones restantes estaban en el SslStream
mismo: el búfer de 4000 para protocolos de enlace TLS y el búfer de 32 000 para lecturas normales. En .NET 6, cuando el usuario realiza una lectura de cero bytes en SslStream
y no tiene datos disponibles, SslStream
realiza una lectura de cero bytes de manera interna en la secuencia ajustada subyacente. En el mejor de los casos (conexión inactiva), estos cambios generan un ahorro de 40 KB por conexión, a la vez que permiten que el usuario (Kestrel) reciba una notificación cuando los datos estén disponibles in mantener ningún búfer no utilizado.
Lecturas de cero bytes con PipeReader
Como SslStream
admitía las lecturas sin búfer, se agregó una opción para realizar lecturas de cero bytes a StreamPipeReader
, el tipo interno que adapta un Stream
en un PipeReader
. En Kestrel, se usa un StreamPipeReader
para adaptar el SslStream
subyacente a un PipeReader
. Por lo tanto, era necesario exponer esta semántica de la lectura de cero bytes en PipeReader
.
Ahora se puede crear un PipeReader
que admita lecturas de cero bytes en cualquier Stream
subyacente que admita la semántica de lectura de cero bytes (por ejemplo, SslStream
, NetworkStream, etc) con la API siguiente:
var reader = PipeReader.Create(stream, new StreamPipeReaderOptions(useZeroByteReads: true));
Eliminación de bloques de SlabMemoryPool
A fin de reducir la fragmentación del montón, Kestrel utilizó una técnica en la que asignaba bloques de memoria de 128 KB como parte de su grupo de memoria. Luego, los bloques se dividían en bloques de 4 KB que Kestrel usaba de manera interna. Los bloques debían tener más de 85 KB para forzar la asignación en el montón de objetos de gran tamaño para intentar impedir que el GC reasignara esta matriz. Sin embargo, con la introducción de la generación nueva de GC, Montón de objetos anclados (POH), ya no tiene sentido asignar bloques secundarios en el bloque mayor. Kestrel ahora asigna directamente bloques en el Montón de objetos anclados, lo que disminuye la complejidad que implica la administración del grupo de memoria. Este cambio debería facilitar las mejoras futuras, como la reducción del grupo de memoria que Kestrel usa.
IAsyncDisposable compatible
IAsyncDisposable ahora está disponible para controladores, Razor Pages y componentes de vista. Se agregaron versiones asincrónicas a las interfaces pertinentes en fábricas y activadores:
- Los métodos nuevos ofrecen una implementación de interfaz predeterminada que delega a la versión sincrónica y llama a Dispose.
- Las implementaciones reemplazan la implementación predeterminada y controlan la eliminación de las implementaciones de
IAsyncDisposable
. - Las implementaciones favorecen a
IAsyncDisposable
por sobreIDisposable
cuando se implementan ambas interfaces. - Los controles extensores deben invalidar los métodos nuevos que se incluyen para admitir instancias de
IAsyncDisposable
.
IAsyncDisposable
es beneficioso al trabajar con:
- Enumeradores asincrónicos; por ejemplo, en secuencias asincrónicas.
- Recursos no administrados que tienen operaciones de E/S que consumen muchos recursos que se van a liberar.
Al implementar esta interfaz, utilice el método DisposeAsync
para liberar recursos.
Imagine un controlador que crea y utiliza un Utf8JsonWriter. Utf8JsonWriter
es un recurso IAsyncDisposable
:
public class HomeController : Controller, IAsyncDisposable
{
private Utf8JsonWriter? _jsonWriter;
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
_jsonWriter = new Utf8JsonWriter(new MemoryStream());
}
IAsyncDisposable
debe implementar DisposeAsync
:
public async ValueTask DisposeAsync()
{
if (_jsonWriter is not null)
{
await _jsonWriter.DisposeAsync();
}
_jsonWriter = null;
}
Puerto vcpkg para el cliente de C++ de SignalR
vcpkg es un administrador de paquetes de la línea de comandos multiplataforma para bibliotecas de C y C++. Recientemente, agregamos un puerto a vcpkg
para agregar compatibilidad nativa de CMake
con el cliente de C++ de SignalR. vcpkg
también funciona con MSBuild.
El cliente de SignalR se puede agregar a un proyecto de CMake con el fragmento siguiente cuando el vcpkg esté incluido en el archivo de la cadena de herramientas:
find_package(microsoft-signalr CONFIG REQUIRED)
link_libraries(microsoft-signalr::microsoft-signalr)
Con el fragmento anterior, el cliente de C++ de SignalR está listo para utilizar #include
y se puede usar en un proyecto sin necesidad de configuración adicional. Para obtener un ejemplo completo de una aplicación de C++ que usa el cliente de C++ de SignalR, vea el repositorio halter73/SignalR-Client-Cpp-Sample.
Blazor
Cambios en la plantilla de proyecto
Se hicieron varios cambios en la plantilla de proyecto para las aplicaciones Blazor, incluido el uso del archivo Pages/_Layout.cshtml
para el contenido del diseño que aparecía en el archivo _Host.cshtml
para las aplicaciones Blazor Server anteriores. Para estudiar los cambios, cree una aplicación a partir de una plantilla de proyecto 6.0 o acceda al origen de referencia de ASP.NET Core para las plantillas de proyecto:
Compatibilidad con dependencias nativas de Blazor WebAssembly
Las aplicaciones Blazor WebAssembly pueden usar dependencias nativas compiladas para ejecutarse en WebAssembly. Para más información, vea Dependencias nativas de Blazor WebAssembly en ASP.NET Core.
Compilación de WebAssembly ahead-of-time (AOT) y revinculación en tiempo de ejecución
Blazor WebAssembly admite la compilación Ahead Of Time(AOT), donde puede compilar el código de .NET directamente en WebAssembly. La compilación AOT da como resultado mejoras de rendimiento en tiempo de ejecución a costa de un tamaño de aplicación mayor. Al volver a vincular el entorno de ejecución de WebAssembly de .NET, se recorta el código en tiempo de ejecución sin usar y, por tanto, se mejora la velocidad de descarga. Para más información, consulte Compilación ahead-of-time (AOT) y Revinculación en tiempo de ejecución.
Conservación del estado previamente representado
Blazor admite el estado persistente en una página previamente representada para que no sea necesario volver a crear el estado cuando la aplicación esté totalmente cargada. Para más información, vea Integración y representación previa de componentes Razor de ASP.NET Core.
Límites de error
Los límites de error proporcionan un enfoque práctico para controlar las excepciones en el nivel de interfaz de usuario. Para más información, vea Control de errores en aplicaciones Blazor de ASP.NET Core.
Compatibilidad con SVG
El elemento <foreignObject>
se admite para mostrar HTML arbitrario dentro de un archivo SVG. Para más información, vea Componentes Razor de ASP.NET Core.
Compatibilidad de Blazor Server con la transferencia de matriz de bytes en interoperabilidad de JS
Blazor admite la interoperabilidad de JS de la matriz de bytes optimizada que evita la codificación y decodificación de matrices de bytes en Base64. Para obtener más información, consulte los siguientes recursos:
- Llamada a funciones de JavaScript con métodos de .NET en de ASP.NET CoreBlazor
- Llamada a métodos de .NET desde funciones de JavaScript en ASP.NET Core Blazor
Mejoras en la cadena de consulta
Se mejoró la compatibilidad para trabajar con cadenas de consulta. Para más información, vea Enrutamiento y navegación de Blazor de ASP.NET Core.
Enlace para seleccionar varios elementos
El enlace admite la selección de varias opciones con elementos <input>
. Para obtener más información, consulte los siguientes recursos:
Control de contenido de encabezado (<head>
)
Los componentes Razor pueden modificar el contenido del elemento HTML <head>
de una página, incluido el establecimiento del título de la página (elemento <title>
) y la modificación de metadatos (elementos <meta>
). Para más información, vea Control del contenido de <head>
en aplicaciones Blazor de ASP.NET Core.
Generación de componentes Angular y React
Genere componentes de JavaScript específicos del marco de trabajo a partir de componentes Razor para marcos web, como Angular o React. Para más información, vea Componentes Razor de ASP.NET Core.
Representación de componentes desde JavaScript
Represente los componentes de Razor de manera dinámica desde JavaScript para aplicaciones de JavaScript existentes. Para más información, vea Componentes Razor de ASP.NET Core.
Elementos personalizados
La compatibilidad experimental está disponible para crear elementos personalizados que utilizan interfaces HTML estándar. Para más información, vea Componentes Razor de ASP.NET Core.
Inferencia de tipos genéricos de componentes a partir de componentes antecesores
Un componente antecesor puede organizar en cascada un parámetro de tipo por nombre hasta los descendientes mediante el atributo [CascadingTypeParameter]
nuevo. Para más información, vea Componentes Razor de ASP.NET Core.
Componentes representados dinámicamente
Use el componente integrado DynamicComponent
nuevo para representar los componentes por tipo. Para más información, vea Componentes Razor de ASP.NET Core representados dinámicamente.
Accesibilidad a Blazor mejorada
Use el componente FocusOnNavigate
nuevo para establecer el foco de la interfaz de usuario en un elemento basado en un selector CSS después de navegar de una página a otra. Para más información, vea Enrutamiento y navegación de Blazor de ASP.NET Core.
Compatibilidad con argumentos de eventos personalizados
Blazor admite argumentos de eventos personalizados, que permiten pasar datos arbitrarios a controladores de eventos de .NET con eventos personalizados. Para más información, vea Control de eventos de Blazor en ASP.NET Core.
Parámetros obligatorios
Aplique el atributo [EditorRequired]
nuevo para especificar un parámetro de componente necesario. Para más información, vea Componentes Razor de ASP.NET Core.
Colocación de archivos de JavaScript con páginas, vistas y componentes
La colocación de archivos de JavaScript para páginas, vistas y componentes de Razor es una manera cómoda de organizar scripts en una aplicación. Para más información, vea Interoperabilidad de JavaScript en Blazor de ASP.NET Core (interoperabilidad de JS).
Inicializadores de JavaScript
Los inicializadores de JavaScript ejecutan lógica antes y después de que se carga una aplicación Blazor. Para más información, vea Interoperabilidad de JavaScript en Blazor de ASP.NET Core (interoperabilidad de JS).
Streaming de interoperabilidad de JavaScript
Blazor ahora admite el streaming de datos directamente entre .NET y JavaScript. Para obtener más información, consulte los siguientes recursos:
Restricciones de tipo genérico
Ahora se admiten parámetros de tipo genérico. Para más información, vea Componentes Razor de ASP.NET Core.
Diseño de implementación de WebAssembly
Use un diseño de implementación para habilitar las descargas de aplicaciones Blazor WebAssembly en entornos de seguridad restringida. Para más información, vea Diseño de implementación para aplicaciones Blazor WebAssembly hospedadas en ASP.NET Core.
Artículos nuevos sobre Blazor
Además de las características de Blazor descritas en las secciones anteriores, hay artículos nuevos sobre Blazor disponibles acerca de los temas siguientes:
- Descargas de archivos de Blazor de ASP.NET Core: aprenda a descargar un archivo con la interoperabilidad de streaming nativa de
byte[]
para garantizar una transferencia eficaz al cliente. - Mostrar imágenes y documentos en ASP.NET CoreBlazor: descubre cómo trabajar con imágenes y documentos en aplicaciones Blazor, incluyendo cómo transmitir datos de imágenes y documentos.
Creación de aplicaciones Blazor Hybrid con .NET MAUI, WPF y Windows Forms
Use Blazor Hybrid para combinar marcos de cliente nativos móviles y de escritorio con .NET y Blazor:
- .NET Multi-platform App UI (.NET MAUI) es un marco multiplataforma para crear aplicaciones móviles y de escritorio nativas con C# y XAML.
- Las aplicaciones Blazor Hybrid se pueden crear con Windows Presentation Foundation (WPF) y Windows Forms.
Importante
Blazor Hybrid está en versión preliminar y no se debe usar en aplicaciones de producción hasta la versión final.
Para obtener más información, consulte los siguientes recursos:
- Obtención de una vista previa de la documentación de Blazor Hybrid de ASP.NET Core
- Qué es .NET MAUI
- Blog de Microsoft .NET (categoría: ".NET MAUI")
Kestrel
Actualmente, HTTP/3 está en modo borrador y, por lo tanto, está sujeto a cambios. Todavía no se publica la compatibilidad con HTTP/3 en ASP.NET Core, sino que es una característica en vista previa (GB) incluida en .NET 6.
Kestrel ahora admite HTTP/3. Para más información, vea Uso de HTTP/3 con el servidor web Kestrel de ASP.NET Core y la entrada de blog Compatibilidad con HTTP/3 in .NET 6.
Categorías nuevas de registro de Kestrel para el registro seleccionado
Antes de este cambio, habilitar el registro detallado para Kestrel era demasiado costoso, porque todas las instancias de Kestrel compartían el nombre de la categoría de registro Microsoft.AspNetCore.Server.Kestrel
. Microsoft.AspNetCore.Server.Kestrel
sigue disponible, pero las subcategorías nuevas siguientes permiten un mayor control del registro:
Microsoft.AspNetCore.Server.Kestrel
(categoría actual):ApplicationError
,ConnectionHeadResponseBodyWrite
,ApplicationNeverCompleted
,RequestBodyStart
,RequestBodyDone
,RequestBodyNotEntirelyRead
,RequestBodyDrainTimedOut
,ResponseMinimumDataRateNotSatisfied
,InvalidResponseHeaderRemoved
,HeartbeatSlow
.Microsoft.AspNetCore.Server.Kestrel.BadRequests
:ConnectionBadRequest
,RequestProcessingError
,RequestBodyMinimumDataRateNotSatisfied
.Microsoft.AspNetCore.Server.Kestrel.Connections
:ConnectionAccepted
,ConnectionStart
,ConnectionStop
,ConnectionPause
,ConnectionResume
,ConnectionKeepAlive
ConnectionRejected
,ConnectionDisconnect
,NotAllConnectionsClosedGracefully
, ,NotAllConnectionsAborted
ApplicationAbortedConnection
.Microsoft.AspNetCore.Server.Kestrel.Http2
:Http2ConnectionError
,Http2ConnectionClosing
,Http2ConnectionClosed
,Http2StreamError
,Http2StreamResetAbort
HPackDecodingError
,HPackEncodingError
,Http2FrameReceived
, ,Http2FrameSending
Http2MaxConcurrentStreamsReached
.Microsoft.AspNetCore.Server.Kestrel.Http3
:Http3ConnectionError
,Http3ConnectionClosing
,Http3ConnectionClosed
,Http3StreamAbort
,Http3FrameReceived
,Http3FrameSending
.
Las reglas existentes siguen funcionando, pero ahora puede ser más selectivo respecto de las reglas que habilita. Por ejemplo, la sobrecarga de observabilidad de habilitar el registro de Debug
solo para solicitudes incorrectas se reduce considerablemente y se puede habilitar con la configuración siguiente:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Microsoft.AspNetCore.Kestrel.BadRequests": "Debug"
}
}
El filtrado de registros aplica reglas con el prefijo de categoría coincidente más largo. Para más información, consulte Cómo se aplican las reglas de filtro.
Emisión de KestrelServerOptions a través del evento EventSource
El KestrelEventSource emite un evento nuevo que contiene el KestrelServerOptions serializado por JSON cuando se habilita con el nivel de detalle EventLevel.LogAlways
. Este evento facilita razonar sobre el comportamiento del servidor al analizar los seguimientos recopilados. El JSON siguiente es un ejemplo de la carga del evento:
{
"AllowSynchronousIO": false,
"AddServerHeader": true,
"AllowAlternateSchemes": false,
"AllowResponseHeaderCompression": true,
"EnableAltSvc": false,
"IsDevCertLoaded": true,
"RequestHeaderEncodingSelector": "default",
"ResponseHeaderEncodingSelector": "default",
"Limits": {
"KeepAliveTimeout": "00:02:10",
"MaxConcurrentConnections": null,
"MaxConcurrentUpgradedConnections": null,
"MaxRequestBodySize": 30000000,
"MaxRequestBufferSize": 1048576,
"MaxRequestHeaderCount": 100,
"MaxRequestHeadersTotalSize": 32768,
"MaxRequestLineSize": 8192,
"MaxResponseBufferSize": 65536,
"MinRequestBodyDataRate": "Bytes per second: 240, Grace Period: 00:00:05",
"MinResponseDataRate": "Bytes per second: 240, Grace Period: 00:00:05",
"RequestHeadersTimeout": "00:00:30",
"Http2": {
"MaxStreamsPerConnection": 100,
"HeaderTableSize": 4096,
"MaxFrameSize": 16384,
"MaxRequestHeaderFieldSize": 16384,
"InitialConnectionWindowSize": 131072,
"InitialStreamWindowSize": 98304,
"KeepAlivePingDelay": "10675199.02:48:05.4775807",
"KeepAlivePingTimeout": "00:00:20"
},
"Http3": {
"HeaderTableSize": 0,
"MaxRequestHeaderFieldSize": 16384
}
},
"ListenOptions": [
{
"Address": "https://127.0.0.1:7030",
"IsTls": true,
"Protocols": "Http1AndHttp2"
},
{
"Address": "https://[::1]:7030",
"IsTls": true,
"Protocols": "Http1AndHttp2"
},
{
"Address": "http://127.0.0.1:5030",
"IsTls": false,
"Protocols": "Http1AndHttp2"
},
{
"Address": "http://[::1]:5030",
"IsTls": false,
"Protocols": "Http1AndHttp2"
}
]
}
Evento DiagnosticSource nuevo para solicitudes HTTP rechazadas
Kestrel ahora emite un evento DiagnosticSource
nuevo para solicitudes HTTP rechazadas en la capa de servidor. Antes de este cambio, no había manera de observar estas solicitudes rechazadas. El evento Microsoft.AspNetCore.Server.Kestrel.BadRequest
nuevo de DiagnosticSource
contiene un objeto IBadRequestExceptionFeature que se puede usar para hacer una introspección del motivo para rechazar la solicitud.
using Microsoft.AspNetCore.Http.Features;
using System.Diagnostics;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
var diagnosticSource = app.Services.GetRequiredService<DiagnosticListener>();
using var badRequestListener = new BadRequestEventListener(diagnosticSource,
(badRequestExceptionFeature) =>
{
app.Logger.LogError(badRequestExceptionFeature.Error, "Bad request received");
});
app.MapGet("/", () => "Hello world");
app.Run();
class BadRequestEventListener : IObserver<KeyValuePair<string, object>>, IDisposable
{
private readonly IDisposable _subscription;
private readonly Action<IBadRequestExceptionFeature> _callback;
public BadRequestEventListener(DiagnosticListener diagnosticListener,
Action<IBadRequestExceptionFeature> callback)
{
_subscription = diagnosticListener.Subscribe(this!, IsEnabled);
_callback = callback;
}
private static readonly Predicate<string> IsEnabled = (provider) => provider switch
{
"Microsoft.AspNetCore.Server.Kestrel.BadRequest" => true,
_ => false
};
public void OnNext(KeyValuePair<string, object> pair)
{
if (pair.Value is IFeatureCollection featureCollection)
{
var badRequestFeature = featureCollection.Get<IBadRequestExceptionFeature>();
if (badRequestFeature is not null)
{
_callback(badRequestFeature);
}
}
}
public void OnError(Exception error) { }
public void OnCompleted() { }
public virtual void Dispose() => _subscription.Dispose();
}
Para más información, vea Registro y diagnóstico en Kestrel.
Creación de un objeto ConnectionContext a partir de un socket de aceptación
El objeto SocketConnectionContextFactory nuevo permite crear un objeto ConnectionContext a partir de un socket aceptado. De este modo, es posible crear un objeto IConnectionListenerFactory basado en socket personalizado sin perder todo el trabajo de rendimiento y la agrupación que ocurre en SocketConnection.
Consulte este ejemplo de un objeto IConnectionListenerFactory personalizado que muestra cómo usar esta objeto SocketConnectionContextFactory
.
Kestrel es el perfil de inicio predeterminado para Visual Studio
El perfil de inicio predeterminado para todos los proyectos web dotnet nuevos es Kestrel. El inicio de Kestrel es considerablemente más rápido y genera una experiencia con mayor capacidad de respuesta al desarrollar aplicaciones.
IIS Express sigue disponible como perfil de inicio para escenarios como la autenticación de Windows o el uso compartido de puertos.
Los puertos localhost para Kestrel son aleatorios
Vea Puertos generados por plantillas para Kestrel en este documento para más información.
Autenticación y autorización
Servidores de autenticación
De .NET 3 a .NET 5 se usaba IdentityServer4 como parte de la plantilla para permitir la emisión de tokens JWT para SPA y aplicaciones Blazor. Ahora en las plantillas se usa Duende Identity Server.
Si va a extender los identity modelos y está actualizando los proyectos existentes, actualice los espacios de nombres del código de IdentityServer4.IdentityServer
a Duende.IdentityServer
y siga sus instrucciones de migración.
El modelo de licencia de Duende Identity Server cambió a una licencia recíproca que puede requerir tarifas de licencia si se usa de manera comercial en un entorno de producción. Para más detalles, consulte la página de licencias de Duende.
Negociación retrasada de certificados de cliente
Los desarrolladores ahora pueden optar por usar la negociación retrasada de certificados de cliente. Para ello, deben especificarClientCertificateMode.DelayCertificate en HttpsConnectionAdapterOptions. Esto solo funciona con conexiones HTTP/1.1, porque HTTP/2 prohíbe la renegociación retrasada de certificados. El autor de la llamada de esta API debe almacenar en búfer el cuerpo de la solicitud antes de solicitar el certificado de cliente:
using Microsoft.AspNetCore.Server.Kestrel.Https;
using Microsoft.AspNetCore.WebUtilities;
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseKestrel(options =>
{
options.ConfigureHttpsDefaults(adapterOptions =>
{
adapterOptions.ClientCertificateMode = ClientCertificateMode.DelayCertificate;
});
});
var app = builder.Build();
app.Use(async (context, next) =>
{
bool desiredState = GetDesiredState();
// Check if your desired criteria is met
if (desiredState)
{
// Buffer the request body
context.Request.EnableBuffering();
var body = context.Request.Body;
await body.DrainAsync(context.RequestAborted);
body.Position = 0;
// Request client certificate
var cert = await context.Connection.GetClientCertificateAsync();
// Disable buffering on future requests if the client doesn't provide a cert
}
await next(context);
});
app.MapGet("/", () => "Hello World!");
app.Run();
Evento OnCheckSlidingExpiration
para controlar la renovación de cookie
La expiración deslizante de la autenticación de Cookie ahora se puede personalizar o suprimir mediante el nuevo objeto OnCheckSlidingExpiration. Por ejemplo, este evento lo puede usar una aplicación de página única que necesita hacer ping periódicamente al servidor sin que esto afecte a la sesión de autenticación.
Varios
Recarga activa
Realice actualizaciones rápidas de UI y código en aplicaciones en ejecución sin perder el estado de las aplicaciones a fin de lograr una experiencia más rápida y productiva para el desarrollador mediante Recarga activa. Para obtener más información, vea Compatibilidad de la Recarga activa de .NET con ASP.NET Core y Actualización del progreso de Recarga activa de .NET y aspectos destacados de Visual Studio 2022.
Plantillas de aplicación de página única (SPA) mejoradas
Se actualizaron las plantillas de proyecto de ASP.NET Core para Angular y React con el fin de usar un patrón mejorado para aplicaciones de página única que sea más flexible y que mejor se alinee con los patrones comunes para el desarrollo web de front-end moderno.
Anteriormente, la plantilla de ASP.NET Core para Angular y React usaba middleware especializado durante el desarrollo a fin de iniciar el servidor de desarrollo para el marco de front-end y, a continuación, redirigir mediante proxy las solicitudes desde ASP.NET Core hasta el servidor de desarrollo. La lógica para iniciar el servidor de desarrollo front-end era específica de la interfaz de línea de comandos para el marco de front-end correspondiente. Admitir marcos de front-end adicionales mediante este patrón significaba agregar una lógica adicional a ASP.NET Core.
Las plantillas actualizadas de ASP.NET Core para Angular y React en .NET 6 invierten esta disposición y aprovechan la compatibilidad integrada de proxy en los servidores de desarrollo de la mayoría de los marcos de front-end modernos. Cuando se inicia la aplicación de ASP.NET Core, el servidor de desarrollo front-end se inicia igual que antes, pero el servidor de desarrollo está configurado para redirigir mediante proxy las solicitudes al proceso de ASP.NET Core de back-end. Toda la configuración específica del front-end para configurar el proxy forma parte de la aplicación, no de ASP.NET Core. Ahora es sencillo configurar proyectos de ASP.NET Core para que funcionen con otros marcos de front-end: configure el servidor de desarrollo front-end para el marco elegido a fin de redirigir mediante proxy las solicitudes al back-end de ASP.NET Core mediante el patrón establecido en las plantillas de Angular y React.
El código de inicio de la aplicación ASP.NET Core ya no necesita ninguna lógica específica de aplicación de página única. La lógica para iniciar el servidor de desarrollo front-end durante el desarrollo se inserta en la aplicación en tiempo de ejecución mediante el paquete Microsoft.AspNetCore.SpaProxy nuevo. El enrutamiento de reserva se controla mediante el enrutamiento de puntos de conexión en lugar del middleware específico de SPA.
Las plantillas que siguen este patrón se pueden seguir ejecutando como un proyecto único en Visual Studio o mediante dotnet run
en la línea de comandos. Cuando se publica la aplicación, el código de front-end de la carpeta ClientApp se compila y recopila tal como se hacía antes, en la raíz web de la aplicación host ASP.NET Core, y se implementa como archivos estáticos. Los archivos que están incluidos en la plantilla configuran el servidor de desarrollo front-end para usar HTTPS mediante el uso del certificador de desarrollo de ASP.NET Core.
Borrador de compatibilidad con HTTP/3 en .NET 6
Actualmente, HTTP/3 está en modo borrador y, por lo tanto, está sujeto a cambios. Todavía no se publica la compatibilidad con HTTP/3 en ASP.NET Core, sino que es una característica en vista previa (GB) incluida en .NET 6.
Consulte la entrada de blog sobre compatibilidad con HTTP/3 en .NET 6.
Anotaciones en los tipos de referencia nula
Se han aplicado anotaciones de nulabilidad a algunas partes del código fuente de ASP.NET Core 6.0.
Mediante el uso de la característica nueva de C# 8 que admite un valor NULL, ASP.NET Core puede proporcionar seguridad adicional en tiempo de compilación en el control de los tipos de referencia. Por ejemplo, protección frente a excepciones de referencia null
. Los proyectos que han optado por utilizar anotaciones que admiten un valor NULL pueden ver advertencias en tiempo de compilación nuevas de las API de ASP.NET Core.
Si desea habilitar los tipos de referencia que admiten un valor NULL, agregue la propiedad siguiente a los archivos de proyecto:
<PropertyGroup>
<Nullable>enable</Nullable>
</PropertyGroup>
Para más información, consulte Tipos de referencia que admiten un valor NULL.
Análisis de código fuente
Se agregaron varios analizadores de plataforma del compilador .NET que inspeccionan el código de la aplicación para buscar problemas como la configuración o el orden de middleware incorrecto, conflictos de enrutamiento, entre otros. Para más información, consulte Análisis de código en aplicaciones ASP.NET Core.
Mejoras en las plantillas de aplicación web
Las plantillas de aplicación web:
- Usan el modelo de hospedaje mínimo nuevo.
- Reducen considerablemente la cantidad de archivos y líneas de código que se necesitan para crear una aplicación. Por ejemplo, la aplicación web ASP.NET Core vacía crea un archivo de C# con cuatro líneas de código y es una aplicación completa.
- Unifican
Startup.cs
yProgram.cs
en un archivoProgram.cs
único. - Utilizan instrucciones de nivel superior a fin de minimizar el código necesario para una aplicación.
- Utilizan directivas
using
globales a fin de eliminar o minimizar la cantidad de líneas de instrucciónusing
que se requieren.
Puertos generados por plantilla para Kestrel
Se asignan puertos aleatorios durante la creación del proyecto a fin de que los user el servidor web Kestrel. Los puertos aleatorios ayudan a minimizar la posibilidad de conflicto de puertos cuando se ejecutan varios proyectos en la misma máquina.
Cuando se crea un proyecto, se especifica un puerto HTTP aleatorio entre 5000 y 5300 y un puerto HTTPS aleatorio entre 7000 y 7300 en el archivo Properties/launchSettings.json
generado. Puede cambiar los puertos en el archivo Properties/launchSettings.json
. Si no se especifica ningún puerto, Kestrel utiliza de manera predeterminada los puertos HTTP 5000 y HTTPS 5001. Para más información, vea Configuración de puntos de conexión para el servidor web Kestrel de ASP.NET Core.
Valores predeterminados de registro nuevos
Se hicieron los cambios siguientes en appsettings.json
y appsettings.Development.json
:
- "Microsoft": "Warning",
- "Microsoft.Hosting.Lifetime": "Information"
+ "Microsoft.AspNetCore": "Warning"
El cambio de "Microsoft": "Warning"
a "Microsoft.AspNetCore": "Warning"
genera el registro de todos los mensajes informativos del espacio de nombres Microsoft
excepto Microsoft.AspNetCore
. Por ejemplo, Microsoft.EntityFrameworkCore
ahora se registra en el nivel informativo.
Se agregó automáticamente el middleware de la página de excepciones para el desarrollador
En el entorno de desarrollo, DeveloperExceptionPageMiddleware se agrega de manera predeterminada. Ya no es necesario agregar el código siguiente a las aplicaciones de interfaz de usuario web:
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
Compatibilidad con encabezados de solicitud con codificación Latin1 en HttpSysServer
HttpSysServer
ahora admite la descodificación de los encabezados de solicitud con codificación Latin1
mediante el establecimiento de la propiedad UseLatin1RequestHeaders de HttpSysOptions en true
:
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseHttpSys(o => o.UseLatin1RequestHeaders = true);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Los registros del módulo ASP.NET Core incluyen marcas de tiempo y PID
Los registros de diagnóstico mejorados del módulo ASP.NET Core (ANCM) para IIS incluyen marcas de tiempo y PID del proceso que emite los registros. El registro de marcas de tiempo y PID facilita el diagnóstico de problemas con reinicios de procesos superpuestos en IIS cuando se ejecutan varios procesos de trabajo de IIS.
Los registros resultantes ahora son similares a la salida de ejemplo que se muestra a continuación:
[2021-07-28T19:23:44.076Z, PID: 11020] [aspnetcorev2.dll] Initializing logs for 'C:\<path>\aspnetcorev2.dll'. Process Id: 11020. File Version: 16.0.21209.0. Description: IIS ASP.NET Core Module V2. Commit: 96475a2acdf50d7599ba8e96583fa73efbe27912.
[2021-07-28T19:23:44.079Z, PID: 11020] [aspnetcorev2.dll] Resolving hostfxr parameters for application: '.\InProcessWebSite.exe' arguments: '' path: 'C:\Temp\e86ac4e9ced24bb6bacf1a9415e70753\'
[2021-07-28T19:23:44.080Z, PID: 11020] [aspnetcorev2.dll] Known dotnet.exe location: ''
Tamaño de búfer entrante no utilizado configurable para IIS
Anteriormente, el servidor IIS solo almacenaba en búfer 64 KiB de cuerpos de solicitud no utilizados. El almacenamiento en búfer de 64 KiB dio lugar a que las lecturas se limitaran a ese tamaño máximo, lo que afecta al rendimiento con cuerpos entrantes de gran tamaño, como las cargas. En .NET 6, el tamaño de búfer predeterminado cambia de 64 KiB a 1 MiB, lo que debería mejorar el rendimiento para cargas de gran tamaño. En las pruebas que hemos realizado, una carga de 700 MiB que solía tardar 9 s ahora solo tarda 2,5 s.
La desventaja de un tamaño de búfer mayor es que aumenta el consumo de memoria por solicitud cuando la aplicación no lee rápidamente desde el cuerpo de la solicitud. Por lo tanto, además de cambiar el tamaño de búfer predeterminado, el tamaño del búfer se puede configurar, lo que permite que las aplicaciones configuren el tamaño del búfer en función de la carga de trabajo.
Asistentes de etiquetas para componentes de vista
Imagine un componente de vista con un parámetro opcional, tal como se muestra en el código siguiente:
class MyViewComponent
{
IViewComponentResult Invoke(bool showSomething = false) { ... }
}
Con ASP.NET Core 6, se puede invocar al asistente de etiquetas sin que sea necesario especificar un valor para el parámetro showSomething
:
<vc:my />
La plantilla de Angular se actualizó a Angular 12
La plantilla de ASP.NET Core 6.0 para Angular ahora usa Angular 12.
La plantilla de React se actualizó a React 17.
Umbral de búfer configurable antes de escribir en el disco en el formateador de salida Json.NET
Nota: Se recomienda usar el formateador de salida System.Text.Json, excepto cuando se necesita el serializador Newtonsoft.Json
por motivos de compatibilidad. El serializador System.Text.Json
es completamente async
y funciona de manera eficaz para cargas mayores.
De manera predeterminada, el formateador de salida Newtonsoft.Json
almacena en búfer respuestas de hasta 32 KiB en memoria antes de realizar el almacenamiento en búfer en el disco. Esto es para evitar realizar E/S sincrónica, lo que puede generar otros efectos secundarios, como la falta de subprocesos e interbloqueos de aplicaciones. Sin embargo, si la respuesta tiene más de 32 KiB, se produce una E/S de disco considerable. Ahora, puede configurar el umbral de memoria con la propiedad MvcNewtonsoftJsonOptions.OutputFormatterMemoryBufferThreshold antes de realizar el almacenamiento en búfer en el disco:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages()
.AddNewtonsoftJson(options =>
{
options.OutputFormatterMemoryBufferThreshold = 48 * 1024;
});
var app = builder.Build();
Para más información, consulte esta solicitud de incorporación de cambios de GitHub y el archivo NewtonsoftJsonOutputFormatterTest.cs.
Obtención y configuración más rápidas de encabezados HTTP
Se agregaron API nuevas para exponer todos los encabezados comunes disponibles en Microsoft.Net.Http.Headers.HeaderNames como propiedades IHeaderDictionary, lo que genera una API más fácil de usar. Por ejemplo, el middleware insertado en el código siguiente usa las API nuevas para obtener y configurar tanto los encabezados de solicitud como los de respuesta:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Use(async (context, next) =>
{
var hostHeader = context.Request.Headers.Host;
app.Logger.LogInformation("Host header: {host}", hostHeader);
context.Response.Headers.XPoweredBy = "ASP.NET Core 6.0";
await next.Invoke(context);
var dateHeader = context.Response.Headers.Date;
app.Logger.LogInformation("Response date: {date}", dateHeader);
});
app.Run();
En el caso de los encabezados implementados, se implementan los descriptores de acceso get y set directamente en el campo, omitiendo la búsqueda. En el caso de los encabezados no implementados, los descriptores de acceso pueden omitir la búsqueda inicial respecto de los encabezados implementados y realizar directamente la búsqueda de Dictionary<string, StringValues>
. Evitar la búsqueda genera un acceso más rápido en ambos escenarios.
Streaming asincrónico
ASP.NET Core ahora admite el streaming asincrónico de las acciones del controlador y las respuestas del formateador JSON. Devolver un objeto IAsyncEnumerable
a partir de una acción ya no almacena en búfer el contenido de la respuesta en memoria antes de que se envíe. No almacenar en búfer ayuda a reducir el uso de memoria al devolver conjuntos de datos de gran tamaño que se pueden enumerar de manera asincrónica.
Tenga en cuenta que Entity Framework Core proporciona implementaciones de IAsyncEnumerable
para consultar la base de datos. La compatibilidad mejorada con IAsyncEnumerable
en ASP.NET Core en .NET 6 puede usar EF Core con ASP.NET Core con mayor eficacia. Por ejemplo, el código siguiente ya no almacena en búfer los datos del producto en memoria antes de enviar la respuesta:
public IActionResult GetMovies()
{
return Ok(_context.Movie);
}
Sin embargo, al usar la carga diferida en EF Core, este comportamiento nuevo puede generar errores debido a la ejecución simultánea de consultas mientras se enumeran los datos. Las aplicaciones pueden almacenar en búfer los datos a fin de volver al comportamiento anterior:
public async Task<IActionResult> GetMovies2()
{
return Ok(await _context.Movie.ToListAsync());
}
Consulte el anuncio relacionado para más detalles sobre este cambio en el comportamiento.
Middleware de registro HTTP
El registro HTTP es un middleware integrado nuevo que registra información sobre solicitudes HTTP y respuestas HTTP, incluidos los encabezados y todo el cuerpo:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseHttpLogging();
app.MapGet("/", () => "Hello World!");
app.Run();
Navegue a /
con la información anterior sobre registros de código similar a esta salida:
info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[1]
Request:
Protocol: HTTP/2
Method: GET
Scheme: https
PathBase:
Path: /
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cache-Control: max-age=0
Connection: close
Cookie: [Redacted]
Host: localhost:44372
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36 Edg/95.0.1020.30
sec-ch-ua: [Redacted]
sec-ch-ua-mobile: [Redacted]
sec-ch-ua-platform: [Redacted]
upgrade-insecure-requests: [Redacted]
sec-fetch-site: [Redacted]
sec-fetch-mode: [Redacted]
sec-fetch-user: [Redacted]
sec-fetch-dest: [Redacted]
info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[2]
Response:
StatusCode: 200
Content-Type: text/plain; charset=utf-8
La salida anterior se habilitó con el archivo appsettings.Development.json
siguiente:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "Information"
}
}
}
El registro HTTP proporciona registros de:
- Información de solicitud HTTP
- Propiedades comunes
- Encabezados
- Cuerpo
- Información de respuesta HTTP
Si desea configurar el middleware de registro HTTP, especifique HttpLoggingOptions:
using Microsoft.AspNetCore.HttpLogging;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(logging =>
{
// Customize HTTP logging.
logging.LoggingFields = HttpLoggingFields.All;
logging.RequestHeaders.Add("My-Request-Header");
logging.ResponseHeaders.Add("My-Response-Header");
logging.MediaTypeOptions.AddText("application/javascript");
logging.RequestBodyLogLimit = 4096;
logging.ResponseBodyLogLimit = 4096;
});
var app = builder.Build();
app.UseHttpLogging();
app.MapGet("/", () => "Hello World!");
app.Run();
IConnectionSocketFeature
La característica de solicitud IConnectionSocketFeature proporciona acceso al socket de aceptación subyacente asociado con la solicitud actual. Se puede obtener acceso a través de FeatureCollection en HttpContext
.
Por ejemplo, la aplicación siguiente establece la propiedad LingerState en el socket aceptado:
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(serverOptions =>
{
serverOptions.ConfigureEndpointDefaults(listenOptions => listenOptions.Use((connection, next) =>
{
var socketFeature = connection.Features.Get<IConnectionSocketFeature>();
socketFeature.Socket.LingerState = new LingerOption(true, seconds: 10);
return next();
}));
});
var app = builder.Build();
app.MapGet("/", (Func<string>)(() => "Hello world"));
await app.RunAsync();
Restricciones de tipo genérico en Razor
Al definir parámetros de tipo genérico en Razor mediante la directiva @typeparam
, ahora se pueden especificar las restricciones de tipo genérico mediante la sintaxis estándar de C#:
Scripts más pequeños de SignalR, Blazor Server y MessagePack
Los scripts de SignalR, MessagePack y Blazor Server ahora son considerablemente más pequeños, lo que permite realizar descargar más pequeñas, menos análisis y compilación de JavaScript por parte del explorador, además de un inicio más rápido. Reducciones de tamaño:
signalr.js
: 70 %blazor.server.js
: 45 %
Los scripts más pequeños son el resultado de una contribución de la comunidad por parte de Ben Adams. Para más información sobre los detalles de la reducción de tamaño, consulte la solicitud de incorporación de cambios de GitHub de Ben.
Habilitación de sesiones de generación de perfiles en Redis
Una contribución de la comunidad de Gabriel Lucaci permite una sesión de generación de perfiles en Redis con Microsoft.Extensions.Caching.StackExchangeRedis:
using StackExchange.Redis.Profiling;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddStackExchangeRedisCache(options =>
{
options.ProfilingSession = () => new ProfilingSession();
});
Para más información, consulte el artículo sobre la generación de perfiles StackExchange.Redis.
Instantáneas en IIS
Se agregó una característica experimental al módulo ASP.NET Core (ANCM) para IIS a fin de agregar compatibilidad con los ensamblados de la aplicación de instantáneas. Actualmente, .NET bloquea los archivos binarios de la aplicación al ejecutarse en Windows, lo que hace imposible reemplazar los archivos binarios cuando se ejecuta la aplicación. Si bien nuestra recomendación sigue siendo usar un archivo de aplicación sin conexión, entendemos que hay escenarios en los que no es posible hacerlo; por ejemplo, en implementaciones de FTP.
En tales escenarios, habilite la instantánea mediante la personalización de la configuración del controlador del módulo ASP.NET Core. En la mayoría de los casos, las aplicaciones ASP.NET Core no tienen un elemento web.config
incluido en el código fuente que pueda modificar. En ASP.NET Core, web.config
lo suele generar el SDK. Para empezar, puede usar el web.config
de ejemplo siguiente:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<!-- To customize the asp.net core module uncomment and edit the following section.
For more info see https://go.microsoft.com/fwlink/?linkid=838655 -->
<system.webServer>
<handlers>
<remove name="aspNetCore"/>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified"/>
</handlers>
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout">
<handlerSettings>
<handlerSetting name="experimentalEnableShadowCopy" value="true" />
<handlerSetting name="shadowCopyDirectory" value="../ShadowCopyDirectory/" />
<!-- Only enable handler logging if you encounter issues-->
<!--<handlerSetting name="debugFile" value=".\logs\aspnetcore-debug.log" />-->
<!--<handlerSetting name="debugLevel" value="FILE,TRACE" />-->
</handlerSettings>
</aspNetCore>
</system.webServer>
</configuration>
La instantánea en IIS es una característica experimental y no se garantiza que forme parte de ASP.NET Core. Deje comentarios sobre las instantáneas de IIS en este problema de GitHub.