Compatibilidad de ASP.NET Core con AOT nativo

De Mitch Denny

La publicación e implementación de aplicaciones nativas de antemano (AOT) en ASP.NET Core ofrece varias ventajas:

  • Superficie de disco minimizada. Al publicar una aplicación mediante AOT nativo, el proceso genera un único archivo ejecutable. El ejecutable contiene solo el código de las dependencias externas necesarias para admitir la aplicación. El tamaño de archivo ejecutable reducido puede dar lugar a:

    • Imágenes de contenedor más pequeñas; por ejemplo, en escenarios de implementación en contenedores.
    • Reducción del tiempo de implementación gracias a imágenes más pequeñas.
  • Tiempo de inicio reducido. Las aplicaciones AOT nativas pueden requerir menos tiempo de inicio, lo que permite:

    • La aplicación para acelerar la gestión de solicitudes.
    • Implementación mejorada, donde los orquestadores de contenedores administran la transición de una versión de aplicación a otra.
  • Reducción de la demanda de memoria. Las aplicaciones AOT nativas pueden requerir menos memoria, en función del trabajo realizado por la aplicación. El menor consumo de memoria puede dar lugar a una mayor densidad de implementación y a una mejor escalabilidad.

En el gráfico siguiente se muestran los resultados de una prueba comparativa en las distintas aplicaciones de plantilla. La prueba comparativa compara el rendimiento de una aplicación publicada de AOT (barra naranja), una aplicación en tiempo de ejecución recortada (barra verde) y una aplicación en tiempo de ejecución no recortada (barra amarilla). La prueba reveló que la aplicación AOT nativa muestra un menor tamaño de la aplicación, el uso de memoria y el tiempo de inicio.

Gráfico que muestra una comparación del tamaño de la aplicación, el uso de memoria y las métricas de tiempo de inicio. El gráfico compara una aplicación AOT nativa publicada, una aplicación en tiempo de ejecución recortada y una aplicación en tiempo de ejecución no recortada.

En este artículo se describe la compatibilidad con aplicaciones AOT nativas en ASP.NET Core, incluida una introducción a la publicación e implementación.

Para conocer la guía de compilación nativa AOT en ASP.NET Core Blazor WebAssembly, que agrega o reemplaza las instrucciones de este artículo, consulte las herramientas de compilación y la compilación anticipada (AOT) de ASP.NET Core Blazor WebAssembly.

Revisión de la compatibilidad de ASP.NET Core y AOT nativa

No todas las características de ASP.NET Core son actualmente compatibles con AOT nativo.

En la tabla siguiente se resume la compatibilidad de las características de ASP.NET Core con AOT nativo:

Característica Soportado Soporte parcial No soportado
Blazor Server
CORS ✔️
gRPC ✔️
HealthChecks ✔️
HttpLogging ✔️
Autenticación JWT ✔️
Localización ✔️
API mínimas ✔️
MVC
Otra autenticación
OutputCaching ✔️
Limitación de tasa ✔️
SolicitudDeDescompresión ✔️
Caché de Respuestas ✔️
Compresión de Respuesta ✔️
Reescribir ✔️
Sesión
SignalR ✔️
Balneario
StaticFiles ✔️
WebSockets (protocolo de comunicación web) ✔️

Para obtener más información sobre las limitaciones, consulte:

Comprobación de la aplicación en el modelo de implementación de AOT nativo

Es importante probar una aplicación exhaustivamente al pasar a un modelo de implementación de AOT nativo. Pruebe la aplicación desplegada con AOT y confirme que la funcionalidad es la misma que la de la aplicación compilada en tiempo de ejecución (JIT).

Al crear la aplicación, revise y corrija las advertencias de AOT. Es posible que una aplicación que emite advertencias de AOT durante la publicación no funcione correctamente. Si no se emiten advertencias de AOT en el momento de la publicación, puede esperar que la aplicación AOT publicada funcione igual que la aplicación sin recortar y compilada JIT.

Publicación de una aplicación AOT nativa (PublishAot)

Habilite AOT nativo para la aplicación mediante la PublishAot propiedad MSBuild. En el siguiente ejemplo se muestra cómo habilitar AOT nativo en un archivo de proyecto:

<PropertyGroup>
  <PublishAot>true</PublishAot>
</PropertyGroup>

La PublishAot propiedad habilita la compilación AOT nativa durante el proceso de publicación y habilita el análisis dinámico del uso de código durante la compilación y edición. Un proyecto que usa la publicación de AOT nativa implementa la compilación JIT cuando se ejecuta localmente.

Una aplicación AOT presenta las siguientes diferencias con respecto a una aplicación compilada por JIT:

  • Las características que no son compatibles con AOT nativo se deshabilitan y producen excepciones en tiempo de ejecución.
  • Un analizador de origen está habilitado para resaltar el código que no es compatible con AOT nativo. En el momento de publicación, se analizará la aplicación completa, incluidos los paquetes NuGet, con fines de compatibilidad.

El análisis nativo de AOT incluye todo el código de aplicación y las bibliotecas de las que depende la aplicación. Revise las advertencias de AOT nativo y tome medidas correctivas. Se recomienda publicar las aplicaciones con frecuencia para detectar problemas lo antes posible en el ciclo de vida de desarrollo.

En .NET 8 y versiones posteriores, los siguientes tipos de aplicación de ASP.NET Core admiten AOT nativo:

Revisión de la plantilla api web (AOT nativa)

La plantilla ASP.NET Core Web API (AOT nativo) (nombre corto webapiaot) crea un proyecto con AOT habilitado. La plantilla difiere de una plantilla de proyecto de API web estándar de las maneras siguientes:

  • Usa solo las API mínimas, ya que MVC aún no es compatible con AOT nativo.
  • Usa la CreateSlimBuilder() API para asegurarse de que solo las características esenciales están habilitadas de forma predeterminada, lo que minimiza el tamaño implementado de la aplicación.
  • Está configurado para escuchar solo en HTTP. Normalmente, un servicio de entrada controla el tráfico HTTPS en implementaciones nativas de la nube.
  • No incluye un perfil de inicio para ejecutarse en IIS o IIS Express.
  • Crea un archivo .http configurado con solicitudes HTTP de ejemplo que se pueden enviar a los puntos de conexión de la aplicación.
  • Incluye una API Todo de ejemplo en lugar del ejemplo de previsión meteorológica.
  • Agrega la PublishAot propiedad al archivo del proyecto, como se ha descrito anteriormente.
  • Habilita los generadores de origen del serializador JSON. Los generadores de código fuente se usan para generar código de serialización en tiempo de compilación, lo cual es necesario para la compilación AOT nativa.

Actualizaciones de código para la serialización JSON (Program.cs)

El código del archivo Program.cs se modifica para proporcionar compatibilidad con la generación de orígenes de serialización JSON.

En el fragmento de código siguiente se muestran los cambios realizados en el código:

using MyFirstAotWebApi;
+using System.Text.Json.Serialization;

-var builder = WebApplication.CreateBuilder();
+var builder = WebApplication.CreateSlimBuilder(args);

+builder.Services.ConfigureHttpJsonOptions(options =>
+{
+  options.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonSerializerContext.Default);
+});

var app = builder.Build();

var sampleTodos = TodoGenerator.GenerateTodos().ToArray();

var todosApi = app.MapGroup("/todos");
todosApi.MapGet("/", () => sampleTodos);
todosApi.MapGet("/{id}", (int id) =>
    sampleTodos.FirstOrDefault(a => a.Id == id) is { } todo
        ? Results.Ok(todo)
        : Results.NotFound());

app.Run();

+[JsonSerializable(typeof(Todo[]))]
+internal partial class AppJsonSerializerContext : JsonSerializerContext
+{
+
+}

Si no modifica el código, System.Text.Json usa la reflexión para serializar y deserializar JSON. La reflexión no se admite en AOT nativo.

Para más información, consulte:

Cambios de código para el perfil de inicio (launchSettings.json)

La plantilla api web (AOT nativa) crea un archivo launchSettings.json . A diferencia de un archivo de inicio estándar, el archivo generado no incluye la iisSettings sección ni el IIS Express perfil.

En el fragmento de código siguiente se muestran las secciones excluidas (color rojo):

{
  "$schema": "http://json.schemastore.org/launchsettings.json",
-  "iisSettings": {
-     "windowsAuthentication": false,
-     "anonymousAuthentication": true,
-     "iisExpress": {
-       "applicationUrl": "http://localhost:11152",
-       "sslPort": 0
-     }
-   },
  "profiles": {
    "http": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "launchUrl": "todos",
      "applicationUrl": "http://localhost:5102",
        "environmentVariables": {
          "ASPNETCORE_ENVIRONMENT": "Development"
        }
      },
-     "IIS Express": {
-       "commandName": "IISExpress",
-       "launchBrowser": true,
-       "launchUrl": "todos",
-      "environmentVariables": {
-       "ASPNETCORE_ENVIRONMENT": "Development"
-      }
-    }
  }
}

CreateSlimBuilder() llamado para los valores predeterminados mínimos de la aplicación

La plantilla api web (AOT nativa) usa el CreateSlimBuilder() método en lugar del CreateBuilder() método .

using System.Text.Json.Serialization;
using MyFirstAotWebApi;

var builder = WebApplication.CreateSlimBuilder(args);
builder.Logging.AddConsole();

builder.Services.ConfigureHttpJsonOptions(options =>
{
    options.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonSerializerContext.Default);
});

var app = builder.Build();

var sampleTodos = TodoGenerator.GenerateTodos().ToArray();

var todosApi = app.MapGroup("/todos");
todosApi.MapGet("/", () => sampleTodos);
todosApi.MapGet("/{id}", (int id) =>
    sampleTodos.FirstOrDefault(a => a.Id == id) is { } todo
        ? Results.Ok(todo)
        : Results.NotFound());

app.Run();

[JsonSerializable(typeof(Todo[]))]
internal partial class AppJsonSerializerContext : JsonSerializerContext
{
}

El método CreateSlimBuilder inicializa WebApplicationBuilder con las características de ASP.NET Core mínimas necesarias para ejecutar una aplicación.

Como se ha descrito anteriormente, el CreateSlimBuilder método no incluye compatibilidad con HTTPS o HTTP/3. Normalmente, estos protocolos no son necesarios para las aplicaciones que se ejecutan detrás de un proxy de terminación TLS. Por ejemplo, vea Terminación TLS y TLS de un extremo a otro con Application Gateway. Puede habilitar HTTPS llamando al builder.WebHost.UseKestrelHttpsConfiguration o habilitar HTTP/3 llamando al builder.WebHost.UseQuic.

Comparar CreateSlimBuilder() y CreateBuilder()

El CreateSlimBuilder método proporciona acceso a una parte de las características de la aplicación disponibles con el CreateBuilder método . Como se ha descrito anteriormente, la plantilla Web API (AOT nativo) llama a CreateSlimBuilder para inicializar WebApplicationBuilder, por lo que el generador usa las características mínimas de ASP.NET Core necesarias para ejecutar la aplicación.

Ambos métodos proporcionan las características necesarias para una experiencia de desarrollo eficaz:

  • Configuración de los archivos appsettings.json y appsettings.{EnvironmentName}.json
  • Configuración de secretos de usuario
  • Registro de consola
  • Configuración de registro

Incluir las características mínimas es beneficioso para el recorte, así como para AOT. Para obtener más información, vea Recorte de implementaciones autocontenidas y ejecutables.

Si prefiere usar un generador que omita todas las características, consulte el método WebApplication.CreateEmptyBuilder .

Características no disponibles en CreateSlimBuilder

El CreateSlimBuilder método no proporciona las siguientes características, que están disponibles en CreateBuilder:

Para obtener información más detallada, vea Comparar WebApplication.CreateBuilder con CreateSlimBuilder.

Usar generadores de código fuente y evitar la reflexión

Durante el proceso de publicación de AOT nativo, se recorta cualquier código sin usar. Como resultado, una aplicación no puede usar la reflexión ilimitada en tiempo de ejecución. Puede usar generadores de origen que generan código que evita la necesidad de reflexión. En algunos casos, los generadores de origen generan código optimizado para AOT incluso cuando no se requiere un generador.

  • Para ver el código fuente generado, agregue la propiedad EmitCompilerGeneratedFiles al archivo del proyecto de aplicación (.csproj):

    <Project Sdk="Microsoft.NET.Sdk.Web">
    
       <PropertyGroup>
         <!-- Other properties omitted for brevity -->
         <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
       </PropertyGroup>
    
    </Project>
    
  • Para ver el código generado, ejecute el dotnet build comando . El comando compila los archivos de origen y genera los archivos intermedios necesarios para ejecutar la aplicación en un entorno de desarrollo. La salida incluye un directorio obj/Debug/<.NET version>/generated/ que contiene todos los archivos generados para el proyecto.

  • Para preparar la aplicación para la implementación, ejecute el dotnet publish comando . El comando compila los archivos de origen y genera todos los archivos necesarios para implementar la aplicación. Pasa los ensamblados generados a un compilador de IL nativo, que genera el ejecutable nativo. El archivo ejecutable nativo contiene el código de máquina nativo.

Uso de bibliotecas con AOT nativo

Muchas bibliotecas populares usadas en ASP.NET Core proyectos actualmente tienen algunos problemas de compatibilidad cuando se incorporan a proyectos que tienen como destino AOT nativo, como:

  • Uso de la reflexión para inspeccionar y detectar tipos
  • Carga de bibliotecas condicionalmente en tiempo de ejecución
  • Generación de código sobre la marcha para implementar la funcionalidad

Las bibliotecas que usan estas características dinámicas requieren actualizaciones para trabajar con AOT nativo. Hay varias herramientas disponibles para aplicar las actualizaciones necesarias, como los generadores de origen de Roslyn.

Se recomienda a los autores de bibliotecas que deseen admitir AOT nativo que revisen los siguientes artículos.

Trabaja con APIs mínimas y cargas JSON

El marco API mínimo está optimizado para recibir y devolver cargas JSON mediante el uso de System.Text.Json.

  • El espacio de nombres impone requisitos de compatibilidad para JSON y AOT nativo.
  • Requiere el uso del generador de origen System.Text.Json.

Todos los tipos transmitidos como parte del cuerpo HTTP o devueltos por delegados de solicitud en aplicaciones de API mínimas deben configurarse en una JsonSerializerContext instancia. La instancia debe registrarse con la inyección de dependencias de ASP.NET Core.

using System.Text.Json.Serialization;
using MyFirstAotWebApi;

var builder = WebApplication.CreateSlimBuilder(args);
builder.Logging.AddConsole();

builder.Services.ConfigureHttpJsonOptions(options =>
{
    options.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonSerializerContext.Default);
});

var app = builder.Build();

var sampleTodos = TodoGenerator.GenerateTodos().ToArray();

var todosApi = app.MapGroup("/todos");
todosApi.MapGet("/", () => sampleTodos);
todosApi.MapGet("/{id}", (int id) =>
    sampleTodos.FirstOrDefault(a => a.Id == id) is { } todo
        ? Results.Ok(todo)
        : Results.NotFound());

app.Run();

[JsonSerializable(typeof(Todo[]))]
internal partial class AppJsonSerializerContext : JsonSerializerContext
{
}

Un parámetro en el delegado que no está enlazado al cuerpo no necesita ser serializable. Por ejemplo, un parámetro de cadena de consulta puede ser un tipo de objeto enriquecido que implementa IParsable<T>.

public class Todo
{
    public int Id { get; set; }
    public string? Title { get; set; }
    public DateOnly? DueBy { get; set; }
    public bool IsComplete { get; set; }
}

static class TodoGenerator
{
    private static readonly (string[] Prefixes, string[] Suffixes)[] _parts = new[]
        {
            (new[] { "Walk the", "Feed the" }, new[] { "dog", "cat", "goat" }),
            (new[] { "Do the", "Put away the" }, new[] { "groceries", "dishes", "laundry" }),
            (new[] { "Clean the" }, new[] { "bathroom", "pool", "blinds", "car" })
        };
    // Remaining code omitted for brevity.

Revisión de problemas conocidos

Para notificar o revisar problemas con la compatibilidad con AOT nativo en ASP.NET Core, consulte GitHub /dotnet/core/issues #8288).

.NET 8 presenta compatibilidad con .NET native ahead-of-time (AOT).

Razones para usar AOT nativo con ASP.NET Core

La publicación e implementación de una aplicación de AOT nativo proporciona las siguientes ventajas:

  • Superficie de disco minimizada: al publicar con AOT nativo, se genera un único archivo ejecutable que contiene solo el código de las dependencias externas que se necesitan para respaldar el programa. El tamaño reducido de archivo ejecutable puede dar lugar a:
    • Imágenes de contenedor más pequeñas; por ejemplo, en escenarios de implementación en contenedores.
    • Reducción del tiempo de implementación gracias a imágenes más pequeñas.
  • Menor tiempo de inicio: las aplicaciones de AOT nativo logran unos tiempos de inicio reducidos, lo que significa que:
    • La aplicación está lista para atender las solicitudes más rápidamente.
    • La implementación mejora cuando los orquestadores de contenedores necesitan administrar la transición de una versión de la aplicación a otra.
  • Menor demanda de memoria: las aplicaciones de AOT nativo pueden tener una menor demanda de memoria en función del trabajo que la aplicación realice. El menor consumo de memoria puede dar lugar a una mayor densidad de implementación y a una mejor escalabilidad.

Hemos ejecutado la aplicación de plantilla en nuestro laboratorio de pruebas comparativas para cotejar el rendimiento de una aplicación publicada con AOT, de una aplicación en tiempo de ejecución recortada y de una aplicación en tiempo de ejecución sin recortar. En el siguiente gráfico se muestran los resultados de la prueba comparativa:

Gráfico que muestra la comparación de las métricas de tamaño de la aplicación, uso de memoria y tiempo de inicio de una aplicación publicada de AOT, una aplicación en tiempo de ejecución recortada y una aplicación en tiempo de ejecución sin recortar.

En el gráfico anterior se muestra que AOT nativo tiene un tamaño de aplicación, un uso de memoria y un tiempo de inicio más reducidos.

ASP.NET Core y compatibilidad con AOT nativo

No todas las características de ASP.NET Core son actualmente compatibles con AOT nativo. En la tabla siguiente se resume la compatibilidad de las características de ASP.NET Core con AOT nativo:

Característica Compatibilidad total Se admite parcialmente No es compatible
gRPC Compatibilidad total
API mínimas Compatibilidad parcial
MVC No compatible
Blazor Server No compatible
SignalR No compatible
Autenticación JWT Compatibilidad total
Otra autenticación No compatible
CORS Compatibilidad total
HealthChecks Compatibilidad total
HttpLogging Compatibilidad total
Localización Compatibilidad total
OutputCaching Compatibilidad total
Limitación de tasa Compatibilidad total
SolicitudDeDescompresión Compatibilidad total
Caché de Respuestas Compatibilidad total
Compresión de Respuesta Compatibilidad total
Reescribir Compatibilidad total
Sesión No compatible
Balneario No compatible
StaticFiles Compatibilidad total
WebSockets (protocolo de comunicación web) Compatibilidad total

Para obtener más información sobre las limitaciones, consulte:

Al cambiar a un modelo de implementación de AOT nativo, es importante probar una aplicación exhaustivamente. La aplicación de AOT implementada debe probarse para comprobar que la funcionalidad no ha cambiado respecto a la aplicación sin recortar y con compilación JIT. Al compilar la aplicación, examine y corrija las advertencias de AOT. Es posible que una aplicación que emite advertencias de AOT durante la publicación no funcione correctamente. Si no se emiten advertencias de AOT en el momento de la publicación, la aplicación AOT publicada debería funcionar de la misma manera que la aplicación sin recortar y compilada con JIT.

Publicación de AOT nativo

AOT nativo se habilita con la propiedad de MSBuild PublishAot: En el siguiente ejemplo se muestra cómo habilitar AOT nativo en un archivo de proyecto:

<PropertyGroup>
  <PublishAot>true</PublishAot>
</PropertyGroup>

Esta configuración habilita la compilación de AOT nativo durante la publicación y el análisis dinámico del uso de código en el transcurso de la compilación y la edición. Un proyecto que usa la publicación de AOT nativo utiliza la compilación JIT cuando se ejecuta de forma local. Una aplicación AOT presenta las siguientes diferencias con respecto a una aplicación compilada por JIT:

  • Las características que no son compatibles con AOT nativo se deshabilitan y producen excepciones en tiempo de ejecución.
  • Un analizador de origen está habilitado para resaltar el código que no es compatible con AOT nativo. En el momento de publicación, se analizará la aplicación completa, incluidos los paquetes NuGet, con fines de compatibilidad.

El análisis de AOT nativo abarca todo el código de la aplicación y las bibliotecas de las que esta depende. Revise las advertencias de AOT nativo y tome medidas correctivas. Se recomienda publicar las aplicaciones con frecuencia para detectar problemas lo antes posible en el ciclo de vida de desarrollo.

En .NET 8, AOT nativo es compatible con los siguientes tipos de aplicación ASP.NET Core:

Plantilla de API web (AOT nativa)

La plantilla ASP.NET Core Web API (AOT nativa) (nombre corto webapiaot) crea un proyecto con AOT habilitado. La plantilla difiere de la plantilla de proyecto Web API de las siguientes maneras:

  • Usa solo las API mínimas, ya que MVC aún no es compatible con AOT nativo.
  • Usa la API CreateSlimBuilder() para garantizar que solo las características esenciales están habilitadas de forma predeterminada, lo que reduce al mínimo el tamaño implementado de la aplicación.
  • Está configurada para escuchar solo HTTP, ya que en las implementaciones nativas de nube el tráfico HTTPS suele estar controlado por un servicio de entrada.
  • No incluye un perfil de inicio para ejecutarse en IIS o IIS Express.
  • Crea un archivo .http configurado con solicitudes HTTP de ejemplo que se pueden enviar a los puntos de conexión de la aplicación.
  • Incluye una API Todo de ejemplo en lugar del ejemplo de previsión meteorológica.
  • Agrega PublishAot al archivo de proyecto, tal y como hemos visto anteriormente en este artículo.
  • Habilita los generadores de origen del serializador JSON. Los generadores de código fuente se usan para generar código de serialización en tiempo de compilación, lo cual es necesario para la compilación AOT nativa.

Cambios para apoyar la generación de código fuente

En el siguiente ejemplo se muestra el código agregado al archivo Program.cs para admitir la generación de orígenes de serialización JSON:

using MyFirstAotWebApi;
+using System.Text.Json.Serialization;

-var builder = WebApplication.CreateBuilder();
+var builder = WebApplication.CreateSlimBuilder(args);

+builder.Services.ConfigureHttpJsonOptions(options =>
+{
+  options.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonSerializerContext.Default);
+});

var app = builder.Build();

var sampleTodos = TodoGenerator.GenerateTodos().ToArray();

var todosApi = app.MapGroup("/todos");
todosApi.MapGet("/", () => sampleTodos);
todosApi.MapGet("/{id}", (int id) =>
    sampleTodos.FirstOrDefault(a => a.Id == id) is { } todo
        ? Results.Ok(todo)
        : Results.NotFound());

app.Run();

+[JsonSerializable(typeof(Todo[]))]
+internal partial class AppJsonSerializerContext : JsonSerializerContext
+{
+
+}

Sin este código agregado, System.Text.Json usa la reflexión para serializar y deserializar JSON. La reflexión no se admite en AOT nativo.

Para más información, consulte:

Cambios en launchSettings.json

El archivo launchSettings.json creado por la plantilla de API web (AOT nativo) tiene la sección iisSettings y el perfil IIS Express quitados:

{
  "$schema": "http://json.schemastore.org/launchsettings.json",
-  "iisSettings": {
-     "windowsAuthentication": false,
-     "anonymousAuthentication": true,
-     "iisExpress": {
-       "applicationUrl": "http://localhost:11152",
-       "sslPort": 0
-     }
-   },
  "profiles": {
    "http": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "launchUrl": "todos",
      "applicationUrl": "http://localhost:5102",
        "environmentVariables": {
          "ASPNETCORE_ENVIRONMENT": "Development"
        }
      },
-     "IIS Express": {
-       "commandName": "IISExpress",
-       "launchBrowser": true,
-       "launchUrl": "todos",
-      "environmentVariables": {
-       "ASPNETCORE_ENVIRONMENT": "Development"
-      }
-    }
  }
}

El método CreateSlimBuilder

La plantilla usa el método CreateSlimBuilder() en vez del método CreateBuilder().

using System.Text.Json.Serialization;
using MyFirstAotWebApi;

var builder = WebApplication.CreateSlimBuilder(args);
builder.Logging.AddConsole();

builder.Services.ConfigureHttpJsonOptions(options =>
{
    options.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonSerializerContext.Default);
});

var app = builder.Build();

var sampleTodos = TodoGenerator.GenerateTodos().ToArray();

var todosApi = app.MapGroup("/todos");
todosApi.MapGet("/", () => sampleTodos);
todosApi.MapGet("/{id}", (int id) =>
    sampleTodos.FirstOrDefault(a => a.Id == id) is { } todo
        ? Results.Ok(todo)
        : Results.NotFound());

app.Run();

[JsonSerializable(typeof(Todo[]))]
internal partial class AppJsonSerializerContext : JsonSerializerContext
{
}

El método CreateSlimBuilder inicializa WebApplicationBuilder con las características de ASP.NET Core mínimas necesarias para ejecutar una aplicación.

Como hemos señalado anteriormente, el método CreateSlimBuilder no incluye compatibilidad con HTTPS ni HTTP/3. Normalmente, estos protocolos no son necesarios para las aplicaciones que se ejecutan detrás de un proxy de terminación TLS. Por ejemplo, vea Terminación TLS y TLS de un extremo a otro con Application Gateway. HTTPS se puede habilitar llamando a builder.WebHost.UseKestrelHttpsConfiguration HTTP/3 se puede habilitar llamando a builder.WebHost.UseQuic.

CreateSlimBuilder frente a CreateBuilder

El método CreateSlimBuilder no admite las siguientes características compatibles con el método CreateBuilder:

El método CreateSlimBuilder incluye las siguientes características necesarias para una experiencia de desarrollo eficaz:

  • Configuración del archivo JSON para appsettings.json y appsettings.{EnvironmentName}.json.
  • Configuración de secretos de usuario
  • Registro de consolas
  • Configuración del registro

Para obtener un generador que omita las características anteriores, vea El método CreateEmptyBuilder.

Incluir las características mínimas es beneficioso para el recorte, así como para AOT. Para obtener más información, vea Recorte de implementaciones autocontenidas y ejecutables.

Para obtener información más detallada, consulte Comparación WebApplication.CreateBuilder con CreateSlimBuilder

Generadores de código fuente

Dado que el código sin usar se recorta durante la publicación para AOT nativo, la aplicación no puede usar la reflexión sin enlazar en tiempo de ejecución. Los generadores de código fuente sirven para generar código y evitan tener que recurrir a la reflexión. En algunos casos, los generadores de código fuente generan código optimizado para AOT, incluso cuando no es necesario un generador.

Para ver el código fuente generado, agregue la propiedad EmitCompilerGeneratedFiles al archivo .csproj de una aplicación, como se muestra en el siguiente ejemplo:

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

  <PropertyGroup>
    <!-- Other properties omitted for brevity -->
    <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
  </PropertyGroup>

</Project>

Ejecute el comando dotnet build para ver el código generado. La salida incluye un directorio obj/Debug/net8.0/generated/ que contiene todos los archivos generados del proyecto.

El comando dotnet publish también compila los archivos de origen y genera archivos que se compilan. Asimismo, dotnet publish pasa los ensamblados generados a un compilador de IL nativo. El compilador de IL genera el ejecutable nativo. El archivo ejecutable nativo contiene el código de máquina nativo.

Uso de bibliotecas con AOT nativo

Muchas bibliotecas populares usadas en ASP.NET Core proyectos actualmente tienen algunos problemas de compatibilidad cuando se incorporan a proyectos que tienen como destino AOT nativo, como:

  • Uso de la reflexión para inspeccionar y detectar tipos
  • Carga de bibliotecas condicionalmente en tiempo de ejecución
  • Generación de código sobre la marcha para implementar la funcionalidad

Las bibliotecas que usan estas características dinámicas requieren actualizaciones para trabajar con AOT nativo. Hay varias herramientas disponibles para aplicar las actualizaciones necesarias, como los generadores de origen de Roslyn.

Se anima a los autores de bibliotecas que deseen ser compatibles con AOT nativo a que revisen los artículos siguientes.

API mínimas y cargas de JSON

El marco de API mínimo está optimizado para recibir y devolver cargas JSON mediante System.Text.Json. System.Text.Json:

Todos los tipos que se transmiten como parte del cuerpo HTTP o que se devuelven de delegados de solicitud en aplicaciones de API mínimas deben configurarse en un JsonSerializerContext que se registra a través de la inserción de dependencias de ASP.NET Core:

using System.Text.Json.Serialization;
using MyFirstAotWebApi;

var builder = WebApplication.CreateSlimBuilder(args);
builder.Logging.AddConsole();

builder.Services.ConfigureHttpJsonOptions(options =>
{
    options.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonSerializerContext.Default);
});

var app = builder.Build();

var sampleTodos = TodoGenerator.GenerateTodos().ToArray();

var todosApi = app.MapGroup("/todos");
todosApi.MapGet("/", () => sampleTodos);
todosApi.MapGet("/{id}", (int id) =>
    sampleTodos.FirstOrDefault(a => a.Id == id) is { } todo
        ? Results.Ok(todo)
        : Results.NotFound());

app.Run();

[JsonSerializable(typeof(Todo[]))]
internal partial class AppJsonSerializerContext : JsonSerializerContext
{
}

En el código resaltado anterior:

Parámetro del delegado que no está enlazado al cuerpo y no es necesario serializable. Por ejemplo, un parámetro de cadena de consulta que es un tipo de objeto enriquecido e implementa IParsable<T>.

public class Todo
{
    public int Id { get; set; }
    public string? Title { get; set; }
    public DateOnly? DueBy { get; set; }
    public bool IsComplete { get; set; }
}

static class TodoGenerator
{
    private static readonly (string[] Prefixes, string[] Suffixes)[] _parts = new[]
        {
            (new[] { "Walk the", "Feed the" }, new[] { "dog", "cat", "goat" }),
            (new[] { "Do the", "Put away the" }, new[] { "groceries", "dishes", "laundry" }),
            (new[] { "Clean the" }, new[] { "bathroom", "pool", "blinds", "car" })
        };
    // Remaining code omitted for brevity.

Problemas conocidos

Consulte este problema de GitHub para notificar o revisar los problemas de compatibilidad con AOT nativo en ASP.NET Core.

Consulte también