Partilhar via


Suporte ASP.NET Core para AOT nativo

Por Mitch Denny

Para obter Blazor WebAssembly orientação de AOT nativa, que adiciona ou substitui a orientação neste artigo, consulte Blazor WebAssembly.

Por que usar AOT nativo com ASP.NET Core

Publicar e implantar um aplicativo AOT nativo oferece os seguintes benefícios:

  • Minimized disk footprint: Ao publicar usando AOT nativo, é produzido um único executável que contém apenas o código das dependências externas necessário para suportar o programa. O tamanho reduzido do executável pode levar a:
    • Imagens de contentor mais pequenas, por exemplo, em cenários de implantação em contentores.
    • Tempo de implantação reduzido a partir de imagens menores.
  • Tempo de inicialização reduzido: Os aplicativos AOT nativos podem mostrar tempos de inicialização reduzidos, o que significa
    • O aplicativo está pronto para atender solicitações mais rapidamente.
    • Implantação aprimorada em que os orquestradores de contêineres precisam gerenciar a transição de uma versão do aplicativo para outra.
  • Demanda de memória reduzida: Os aplicativos AOT nativos podem ter demandas de memória reduzidas, dependendo do trabalho feito pelo aplicativo. O consumo reduzido de memória pode levar a uma maior densidade de implantação e melhor escalabilidade.

O aplicativo de modelo foi executado em nosso laboratório de benchmarking para comparar o desempenho de um aplicativo publicado pela AOT, um aplicativo de tempo de execução cortado e um aplicativo de tempo de execução não cortado. O gráfico a seguir mostra os resultados do benchmarking:

Gráfico mostrando a comparação do tamanho do aplicativo, uso de memória e métricas de tempo de inicialização de um aplicativo publicado pela AOT, um aplicativo de tempo de execução cortado e um aplicativo de tempo de execução não cortado.

O gráfico anterior mostra que a AOT nativa tem menor tamanho de aplicativo, uso de memória e tempo de inicialização.

Compatibilidade do ASP.NET Core com AOT nativo

Nem todos os recursos do ASP.NET Core são atualmente compatíveis com a AOT nativa. A tabela a seguir resume a compatibilidade de recursos do ASP.NET Core com o AOT Nativo:

Funcionalidade Totalmente suportado Parcialmente suportado Não suportado
gRPC ✔️ Totalmente suportado
APIs mínimas ✔️ Parcialmente suportado
MVC Não suportado
Blazor Server Não suportado
SignalR ✔️ Parcialmente suportado
Autenticação JWT ✔️ Totalmente suportado
Outra autenticação Não suportado
CORS ✔️ Totalmente suportado
Verificações de saúde ✔️ Totalmente suportado
Registo HTTP ✔️ Totalmente suportado
Localização ✔️ Totalmente suportado
OutputCaching ✔️ Totalmente suportado
Limitação de Taxa ✔️ Totalmente suportado
PedidoDescompressão ✔️ Totalmente suportado
Cache de Respostas ✔️ Totalmente suportado
CompressãoDeResposta ✔️ Totalmente suportado
Reescrever ✔️ Totalmente suportado
Sessão Não suportado
Termas Não suportado
Arquivos Estáticos ✔️ Totalmente suportado
WebSockets ✔️ Totalmente suportado

Para obter mais informações sobre limitações, consulte:

É importante testar um aplicativo completamente ao mudar para um modelo de implantação AOT nativo. O aplicativo compilado pela AOT deve ser testado para garantir que a funcionalidade não sofreu alterações em relação ao aplicativo sem otimização e compilado em JIT. Ao criar o aplicativo, revise e corrija os avisos da AOT. Uma aplicação que emite avisos de AOT durante a publicação pode não funcionar corretamente. Se não forem emitidos avisos de AOT no momento da publicação, a aplicação AOT publicada deverá funcionar da mesma forma que a aplicação não otimizada e compilada em JIT.

Publicação AOT nativa

O Native AOT é habilitado com a propriedade PublishAot MSBuild. O exemplo a seguir mostra como habilitar o AOT nativo em um arquivo de projeto:

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

Essa configuração permite a compilação AOT nativa durante a publicação e permite a análise dinâmica do uso de código durante a compilação e edição. Um projeto que usa a publicação AOT nativa usa a compilação JIT quando executado localmente. Um aplicativo AOT tem as seguintes diferenças de um aplicativo compilado por JIT:

  • Os recursos que não são compatíveis com o AOT nativo são desativados e lançam exceções em tempo de execução.
  • Um analisador de código-fonte está habilitado para destacar o código que não é compatível com o AOT nativo. No momento da publicação, todo o aplicativo, incluindo os pacotes NuGet, é analisado quanto à compatibilidade novamente.

A análise AOT nativa inclui todo o código do aplicativo e as bibliotecas das quais o aplicativo depende. Revise os avisos de AOT nativos e tome medidas corretivas. É uma boa ideia publicar aplicativos com frequência para descobrir problemas no início do ciclo de vida do desenvolvimento.

No .NET 8, a AOT nativa é suportada pelos seguintes tipos de aplicativo ASP.NET Core:

  • APIs mínimas - Para mais informações, consulte a secção do template "The Web API (Native AOT)" mais adiante neste artigo.
  • gRPC - Para mais informações, consulte gRPC e AOT Nativo.
  • Serviços de trabalhador - Para obter mais informações, consulte AOT em Modelos de serviço de trabalhador.

O modelo de API da Web (AOT nativa)

O modelo ASP.NET Core Web API (Native AOT) (nome abreviado webapiaot) cria um projeto com AOT ativado. O modelo difere da API Web modelo de projeto das seguintes maneiras:

  • Usa apenas APIs mínimas, pois o MVC ainda não é compatível com o AOT nativo.
  • Usa a API CreateSlimBuilder() para garantir que apenas os recursos essenciais sejam habilitados por padrão, minimizando o tamanho implantado do aplicativo.
  • Está configurado para escutar somente em HTTP, pois o tráfego HTTPS é normalmente tratado por um serviço de entrada em implantações nativas da nuvem.
  • Não inclui um perfil de inicialização para execução no IIS ou IIS Express.
  • Cria um ficheiro .http configurado com solicitações HTTP de exemplo que podem ser enviadas para os endpoints da aplicação.
  • Inclui uma amostra Todo API em vez da amostra de previsão do tempo.
  • Adiciona PublishAot ao arquivo de projeto, conforme mostrado anteriormente neste artigo.
  • Habilita os geradores de código-fonte do serializador JSON . O gerador de código-fonte é usado para gerar código de serialização em tempo de compilação, o que é necessário para a compilação AOT nativa.

Alterações para dar suporte à geração de código-fonte

O exemplo a seguir mostra o código adicionado ao arquivo Program.cs para dar suporte à geração de origem de serialização 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
+{
+
+}

Sem esse código adicionado, System.Text.Json usa reflexão para serializar e desserializar JSON. A reflexão não é suportada em Native AOT.

Para mais informações, consulte:

Alterações ao launchSettings.json

O arquivo criado pelo modelo de da API Web (AOT nativa) tem a seção e o perfil removidos:

{
  "$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"
-      }
-    }
  }
}

O método CreateSlimBuilder

O modelo usa o método CreateSlimBuilder() em vez do 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
{
}

O método CreateSlimBuilder inicializa o WebApplicationBuilder com o mínimo de recursos ASP.NET Core necessários para executar um aplicativo.

Como observado anteriormente, o método CreateSlimBuilder não inclui suporte para HTTPS ou HTTP/3. Esses protocolos normalmente não são necessários para aplicativos executados atrás de um proxy de terminação TLS. Por exemplo, consulte terminação de TLS e TLS fim a fim com o Application Gateway. O HTTPS pode ser ativado ao invocar construtor.WebHost.UseKestrelHttpsConfiguration. O HTTP/3 pode ser ativado ao invocar construtor.WebHost.UseQuic.

CreateSlimBuilder vs CreateBuilder

O método CreateSlimBuilder não suporta os seguintes recursos que são suportados pelo método CreateBuilder:

O método CreateSlimBuilder inclui os seguintes recursos necessários para uma experiência de desenvolvimento eficiente:

  • Configuração do arquivo JSON para appsettings.json e appsettings.{EnvironmentName}.json.
  • Configuração de segredos do usuário.
  • Registo de consola.
  • Configuração de registo.

Para um construtor que omite as funcionalidades anteriores, consulte o método CreateEmptyBuilder.

A inclusão de características mínimas tem benefícios para a otimização, assim como para o AOT. Para obter mais informações, consulte Reduzir implantações independentes e executáveis.

Para obter informações mais detalhadas, consulte Comparando WebApplication.CreateBuilder com CreateSlimBuilder

Geradores de origem

Como o código não utilizado é cortado durante a publicação para AOT nativo, o aplicativo não pode usar reflexão ilimitada em tempo de execução. Geradores de código-fonte são usados para produzir código que evita a necessidade de reflexão. Em alguns casos, os geradores de código-fonte produzem código otimizado para AOT, mesmo quando um gerador não é necessário.

Para exibir o código-fonte gerado, adicione a propriedade EmitCompilerGeneratedFiles ao arquivo .csproj de um aplicativo, conforme mostrado no exemplo a seguir:

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

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

</Project>

Execute o comando dotnet build para ver o código gerado. A saída inclui um diretório obj/Debug/net8.0/generated/ que contém todos os arquivos gerados para o projeto.

O comando dotnet publish também compila os arquivos de origem e gera arquivos que são compilados. Além disso, dotnet publish passa os assemblies gerados para um compilador IL nativo. O compilador IL produz o executável nativo. O executável nativo contém o código da máquina nativa.

Bibliotecas e AOT nativo

Muitas das bibliotecas populares usadas em projetos ASP.NET Core atualmente têm alguns problemas de compatibilidade quando usadas em um projeto direcionado à AOT nativa, como:

  • Uso da reflexão para inspecionar e descobrir tipos.
  • Carregamento condicional de bibliotecas em tempo de execução.
  • Geração de código em tempo real para implementar funcionalidades.

As bibliotecas que usam esses recursos dinâmicos precisam ser atualizadas para trabalhar com AOT nativo. Eles podem ser atualizados usando ferramentas como geradores de fontes Roslyn.

Os autores de bibliotecas que desejam apoiar o Native AOT são encorajados a:

APIs mínimas e cargas úteis JSON

A API Mínima é otimizada para receber e retornar dados JSON usando System.Text.Json. System.Text.Json:

  • Impõe requisitos de compatibilidade para JSON e AOT nativo.
  • Requer o uso do gerador de fonte System.Text.Json.

Todos os tipos transmitidos como parte do corpo HTTP ou retornados de delegados de solicitação em aplicativos de APIs mínimas devem ser configurados em um JsonSerializerContext registrado por meio da injeção de dependência do 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
{
}

No código destacado anterior:

Um parâmetro no delegado que não está vinculado ao corpo e não precisa ser serializável. Por exemplo, um parâmetro de cadeia de caracteres de consulta que é um tipo de objeto avançado 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 conhecidos

Consulte este problema do GitHub para relatar ou revisar problemas com o suporte nativo de AOT no ASP.NET Core.

Ver também

O .NET 8 introduz suporte para AOT (ahead-of-time) nativo do .NET.

Por que usar AOT nativo com ASP.NET Core

Publicar e implantar um aplicativo AOT nativo oferece os seguintes benefícios:

  • Minimized disk footprint: Ao publicar usando AOT nativo, é produzido um único executável que contém apenas o código das dependências externas necessário para suportar o programa. O tamanho reduzido do executável pode levar a:
    • Imagens de contentor mais pequenas, por exemplo, em cenários de implantação em contentores.
    • Tempo de implantação reduzido a partir de imagens menores.
  • Tempo de inicialização reduzido: Os aplicativos AOT nativos podem mostrar tempos de inicialização reduzidos, o que significa
    • O aplicativo está pronto para atender solicitações mais rapidamente.
    • Implantação aprimorada em que os orquestradores de contêineres precisam gerenciar a transição de uma versão do aplicativo para outra.
  • Demanda de memória reduzida: Os aplicativos AOT nativos podem ter demandas de memória reduzidas, dependendo do trabalho feito pelo aplicativo. O consumo reduzido de memória pode levar a uma maior densidade de implantação e melhor escalabilidade.

O aplicativo de modelo foi executado em nosso laboratório de benchmarking para comparar o desempenho de um aplicativo publicado pela AOT, um aplicativo de tempo de execução cortado e um aplicativo de tempo de execução não cortado. O gráfico a seguir mostra os resultados do benchmarking:

Gráfico mostrando a comparação do tamanho do aplicativo, uso de memória e métricas de tempo de inicialização de um aplicativo publicado pela AOT, um aplicativo de tempo de execução cortado e um aplicativo de tempo de execução não cortado.

O gráfico anterior mostra que a AOT nativa tem menor tamanho de aplicativo, uso de memória e tempo de inicialização.

Compatibilidade do ASP.NET Core com AOT nativo

Nem todos os recursos do ASP.NET Core são atualmente compatíveis com a AOT nativa. A tabela a seguir resume a compatibilidade de recursos do ASP.NET Core com o AOT Nativo:

Funcionalidade Totalmente suportado Parcialmente suportado Não suportado
gRPC ✔️ Totalmente suportado
APIs mínimas ✔️ Parcialmente suportado
MVC Não suportado
Blazor Server Não suportado
SignalR Não suportado
Autenticação JWT ✔️ Totalmente suportado
Outra autenticação Não suportado
CORS ✔️ Totalmente suportado
Verificações de saúde ✔️ Totalmente suportado
Registo HTTP ✔️ Totalmente suportado
Localização ✔️ Totalmente suportado
OutputCaching ✔️ Totalmente suportado
Limitação de Taxa ✔️ Totalmente suportado
PedidoDescompressão ✔️ Totalmente suportado
Cache de Respostas ✔️ Totalmente suportado
CompressãoDeResposta ✔️ Totalmente suportado
Reescrever ✔️ Totalmente suportado
Sessão Não suportado
Termas Não suportado
Arquivos Estáticos ✔️ Totalmente suportado
WebSockets ✔️ Totalmente suportado

Para obter mais informações sobre limitações, consulte:

É importante testar um aplicativo completamente ao mudar para um modelo de implantação AOT nativo. O aplicativo compilado pela AOT deve ser testado para garantir que a funcionalidade não sofreu alterações em relação ao aplicativo sem otimização e compilado em JIT. Ao criar o aplicativo, revise e corrija os avisos da AOT. Uma aplicação que emite avisos de AOT durante a publicação pode não funcionar corretamente. Se não forem emitidos avisos de AOT no momento da publicação, a aplicação AOT publicada deverá funcionar da mesma forma que a aplicação não otimizada e compilada em JIT.

Publicação AOT nativa

O Native AOT é habilitado com a propriedade PublishAot MSBuild. O exemplo a seguir mostra como habilitar o AOT nativo em um arquivo de projeto:

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

Essa configuração permite a compilação AOT nativa durante a publicação e permite a análise dinâmica do uso de código durante a compilação e edição. Um projeto que usa a publicação AOT nativa usa a compilação JIT quando executado localmente. Um aplicativo AOT tem as seguintes diferenças de um aplicativo compilado por JIT:

  • Os recursos que não são compatíveis com o AOT nativo são desativados e lançam exceções em tempo de execução.
  • Um analisador de código-fonte está habilitado para destacar o código que não é compatível com o AOT nativo. No momento da publicação, todo o aplicativo, incluindo os pacotes NuGet, é analisado quanto à compatibilidade novamente.

A análise AOT nativa inclui todo o código do aplicativo e as bibliotecas das quais o aplicativo depende. Revise os avisos de AOT nativos e tome medidas corretivas. É uma boa ideia publicar aplicativos com frequência para descobrir problemas no início do ciclo de vida do desenvolvimento.

No .NET 8, a AOT nativa é suportada pelos seguintes tipos de aplicativo ASP.NET Core:

  • APIs mínimas - Para mais informações, consulte a secção "Modelo de Web API (Native AOT)" mais adiante neste artigo.
  • gRPC - Para mais informações, consulte gRPC e AOT Nativo.
  • Serviços de trabalhador - Para obter mais informações, consulte AOT em Modelos de serviço de trabalhador.

O modelo de API da Web (AOT nativa)

O modelo ASP.NET Core Web API (Native AOT) (nome abreviado webapiaot) cria um projeto com AOT ativado. O modelo difere da API Web modelo de projeto das seguintes maneiras:

  • Usa apenas APIs mínimas, pois o MVC ainda não é compatível com o AOT nativo.
  • Usa a API CreateSlimBuilder() para garantir que apenas os recursos essenciais sejam habilitados por padrão, minimizando o tamanho implantado do aplicativo.
  • Está configurado para escutar somente em HTTP, pois o tráfego HTTPS é normalmente tratado por um serviço de entrada em implantações nativas da nuvem.
  • Não inclui um perfil de inicialização para execução no IIS ou IIS Express.
  • Cria um ficheiro .http configurado com solicitações HTTP de exemplo que podem ser enviadas para os endpoints da aplicação.
  • Inclui uma amostra Todo API em vez da amostra de previsão do tempo.
  • Adiciona PublishAot ao arquivo de projeto, conforme mostrado anteriormente neste artigo.
  • Habilita os geradores de código-fonte do serializador JSON . O gerador de código-fonte é usado para gerar código de serialização em tempo de compilação, o que é necessário para a compilação AOT nativa.

Alterações para dar suporte à geração de código-fonte

O exemplo a seguir mostra o código adicionado ao arquivo Program.cs para dar suporte à geração de origem de serialização 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
+{
+
+}

Sem esse código adicionado, System.Text.Json usa reflexão para serializar e desserializar JSON. A reflexão não é suportada em Native AOT.

Para mais informações, consulte:

Alterações ao launchSettings.json

O arquivo criado pelo modelo de da API Web (AOT nativa) tem a seção e o perfil removidos:

{
  "$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"
-      }
-    }
  }
}

O método CreateSlimBuilder

O modelo usa o método CreateSlimBuilder() em vez do 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
{
}

O método CreateSlimBuilder inicializa o WebApplicationBuilder com o mínimo de recursos ASP.NET Core necessários para executar um aplicativo.

Como observado anteriormente, o método CreateSlimBuilder não inclui suporte para HTTPS ou HTTP/3. Esses protocolos normalmente não são necessários para aplicativos executados atrás de um proxy de terminação TLS. Por exemplo, consulte terminação de TLS e TLS fim a fim com o Application Gateway. O HTTPS pode ser ativado ao invocar construtor.WebHost.UseKestrelHttpsConfiguration. O HTTP/3 pode ser ativado ao invocar construtor.WebHost.UseQuic.

CreateSlimBuilder vs CreateBuilder

O método CreateSlimBuilder não suporta os seguintes recursos que são suportados pelo método CreateBuilder:

O método CreateSlimBuilder inclui os seguintes recursos necessários para uma experiência de desenvolvimento eficiente:

  • Configuração do arquivo JSON para appsettings.json e appsettings.{EnvironmentName}.json.
  • Configuração de segredos do usuário.
  • Registo de consola.
  • Configuração de registo.

Para um construtor que omite as funcionalidades anteriores, consulte o método CreateEmptyBuilder.

A inclusão de características mínimas tem benefícios para a otimização, assim como para o AOT. Para obter mais informações, consulte Reduzir implantações independentes e executáveis.

Para obter informações mais detalhadas, consulte Comparando WebApplication.CreateBuilder com CreateSlimBuilder

Geradores de origem

Como o código não utilizado é cortado durante a publicação para AOT nativo, o aplicativo não pode usar reflexão ilimitada em tempo de execução. Geradores de código-fonte são usados para produzir código que evita a necessidade de reflexão. Em alguns casos, os geradores de código-fonte produzem código otimizado para AOT, mesmo quando um gerador não é necessário.

Para exibir o código-fonte gerado, adicione a propriedade EmitCompilerGeneratedFiles ao arquivo .csproj de um aplicativo, conforme mostrado no exemplo a seguir:

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

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

</Project>

Execute o comando dotnet build para ver o código gerado. A saída inclui um diretório obj/Debug/net8.0/generated/ que contém todos os arquivos gerados para o projeto.

O comando dotnet publish também compila os arquivos de origem e gera arquivos que são compilados. Além disso, dotnet publish passa os assemblies gerados para um compilador IL nativo. O compilador IL produz o executável nativo. O executável nativo contém o código da máquina nativa.

Bibliotecas e AOT nativo

Muitas das bibliotecas populares usadas em projetos ASP.NET Core atualmente têm alguns problemas de compatibilidade quando usadas em um projeto direcionado à AOT nativa, como:

  • Uso da reflexão para inspecionar e descobrir tipos.
  • Carregamento condicional de bibliotecas em tempo de execução.
  • Geração de código em tempo real para implementar funcionalidades.

As bibliotecas que usam esses recursos dinâmicos precisam ser atualizadas para trabalhar com AOT nativo. Eles podem ser atualizados usando ferramentas como geradores de fontes Roslyn.

Os autores de bibliotecas que desejam apoiar o Native AOT são encorajados a:

APIs mínimas e cargas úteis JSON

A API Mínima é otimizada para receber e retornar dados JSON usando System.Text.Json. System.Text.Json:

  • Impõe requisitos de compatibilidade para JSON e AOT nativo.
  • Requer o uso do gerador de fonte System.Text.Json.

Todos os tipos transmitidos como parte do corpo HTTP ou retornados de delegados de solicitação em aplicativos de APIs mínimas devem ser configurados em um JsonSerializerContext registrado por meio da injeção de dependência do 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
{
}

No código destacado anterior:

Um parâmetro no delegado que não está vinculado ao corpo e não precisa ser serializável. Por exemplo, um parâmetro de cadeia de caracteres de consulta que é um tipo de objeto avançado 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 conhecidos

Consulte este problema do GitHub para relatar ou revisar problemas com o suporte nativo de AOT no ASP.NET Core.

Ver também