Suporte do ASP.NET Core ao AOT nativo
Por Mitch Denny
O ASP.NET Core 8.0 é compatível com ahead-of-time (AOT) nativo do .NET.
Consulte as diretrizes de AOT nativo do Blazor WebAssembly, que adicionam ou se sobrepõem às diretrizes deste artigo, em Compilação AOT (antes do tempo) e ferramentas de build do ASP.NET Core Blazor WebAssembly.
Razões para usar o AOT nativo com o ASP.NET Core
Publicar e implantar um aplicativo AOT nativo oferece os seguintes benefícios:
- Volume de disco minimizado: com a publicação por meio do AOT nativo, é produzido um só executável contendo apenas o código de dependências externas necessário para dar suporte ao programa. O tamanho do executável reduzido pode levar a:
- Imagens de contêiner menores, por exemplo, em cenários de implantação em contêineres.
- Tempo de implantação de imagens menores reduzido.
- Tempo de inicialização reduzido: os aplicativos AOT nativos podem mostrar tempos de inicialização reduzidos, o que significa
- Que o aplicativo está pronto para solicitações de serviço 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 executado pelo aplicativo. A redução do consumo de memória pode levar a maior densidade de implantação e escalabilidade aprimorada.
O aplicativo modelo foi executado em nosso laboratório de benchmarking para comparar o desempenho de um aplicativo publicado pelo AOT, um aplicativo de runtime filtrado e um aplicativo de runtime não filtrado. O gráfico a seguir mostra os resultados do benchmarking:
O gráfico anterior mostra que o AOT nativo tem tamanho de aplicativo, uso de memória e tempo de inicialização menores.
Compatibilidade entre o ASP.NET Core e o AOT nativo
Atualmente, nem todos os recursos do ASP.NET Core são compatíveis com o AOT nativo. A seguinte tabela resume a compatibilidade de recursos do ASP.NET Core com o AOT nativo:
Recurso | Totalmente compatível | Suporte parcial | Sem suporte |
---|---|---|---|
gRPC | Totalmente compatível | ||
APIs mínimas | Parcialmente compatível | ||
MVC | Sem suporte | ||
Blazor Server | Sem suporte | ||
SignalR | Parcialmente compatível | ||
Autenticação JWT | Totalmente compatível | ||
Outra autenticação | Sem suporte | ||
CORS | Totalmente compatível | ||
HealthChecks | Totalmente compatível | ||
HttpLogging | Totalmente compatível | ||
Localização | Totalmente compatível | ||
OutputCaching | Totalmente compatível | ||
RateLimiting | Totalmente compatível | ||
RequestDecompression | Totalmente compatível | ||
ResponseCaching | Totalmente compatível | ||
ResponseCompression | Totalmente compatível | ||
Rewrite | Totalmente compatível | ||
Session | Sem suporte | ||
Spa | Sem suporte | ||
StaticFiles | Totalmente compatível | ||
WebSockets | Totalmente compatível |
Para obter mais informações sobre limitações, consulte:
- Limitações da implantação do AOT nativo
- Introdução aos avisos de AOT
- Incompatibilidades de corte conhecidas
- Introdução aos avisos de corte
- GitHub issue dotnet/core #8288
É importante testar um aplicativo minuciosamente ao migrar para um modelo de implantação AOT nativo. O aplicativo AOT implantado deve ser testado para verificar se a funcionalidade não foi alterada em relação ao aplicativo não filtrado e de compilação JIT. Ao compilar o aplicativo, analise e corrija os avisos AOT. Um aplicativo que emite avisos AOT durante a publicação pode não funcionar corretamente. Se nenhum aviso AOT for emitido no momento da publicação, o aplicativo AOT publicado deverá funcionar da mesma forma que o aplicativo compilado por untrimmed e JIT.
Publicação do AOT nativo
O AOT nativo está habilitado com a propriedade MSBuild PublishAot
. O seguinte exemplo mostra como habilitar o AOT nativo em um arquivo de projeto:
<PropertyGroup>
<PublishAot>true</PublishAot>
</PropertyGroup>
Essa configuração habilita a compilação AOT nativo durante a publicação e a análise dinâmica de uso de código durante o build e a edição. Um projeto que usa a publicação AOT nativo usa a compilação JIT ao ser executado localmente. Um aplicativo AOT tem as seguintes diferenças em relação a um aplicativo de compilação JIT:
- Os recursos que não são compatíveis com o AOT nativo são desabilitados e geram exceções em runtime.
- Um analisador de origem está habilitado para realçar o código que não é compatível com o AOT nativo. No momento da publicação, todo o aplicativo, incluindo pacotes NuGet, é analisado para compatibilidade novamente.
A análise AOT nativa inclui todo o código do aplicativo e as bibliotecas das quais o aplicativo depende. Leia os avisos do AOT nativo e realize as etapas corretivas. É uma boa ideia publicar aplicativos com frequência para descobrir problemas no início do ciclo de vida de desenvolvimento.
No .NET 8, o AOT nativo é compatível com os seguintes tipos de aplicativos ASP.NET Core:
- APIs mínimas: para obter mais informações, confira a seção O modelo da API Web (AOT nativo) mais adiante neste artigo.
- gRPC: para obter mais informações, confira gRPC e AOT nativo.
- Serviços de trabalho – para obter mais informações, confira AOT em modelos do Serviço de Trabalho.
O modelo de API Web (AOT nativo)
O modelo de API Web do ASP.NET Core (cujo nome curto é webapiaot
) cria um projeto com o AOT habilitado. O modelo difere do modelo de projeto da API Web 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.
- É configurado para escutar somente HTTP, pois o tráfego HTTPS geralmente é tratado por um serviço de entrada em implantações nativas de nuvem.
- Não inclui um perfil de inicialização para execução no IIS ou no IIS Express.
- Cria um arquivo
.http
configurado com solicitações HTTP de exemplo que podem ser enviadas para os pontos de extremidade do aplicativo. - Inclui uma amostra de API
Todo
em vez da amostra de previsão do tempo. - Adiciona
PublishAot
ao arquivo de projeto, conforme mostrado anteriormente neste artigo. - Habilita os geradores de origem do serializador JSON. O gerador de origem é usado para gerar um código de serialização no momento do build, o que é necessário para a compilação AOT nativo.
Alterações para dar suporte à geração de origem
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 a reflexão para serializar e desserializar o JSON. Não há suporte para reflexão no AOT nativo.
Para saber mais, veja:
Muda para launchSettings.json
O arquivo launchSettings.json
criado pelo modelo de API Web (AOT nativo) tem a seção IIS Express
e o perfil iisSettings
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 os recursos mínimos do ASP.NET Core necessários para executar um aplicativo.
Conforme observado anteriormente, o método CreateSlimBuilder
não é compatível com HTTPS ou HTTP/3. Normalmente, esses protocolos não são necessários para aplicativos executados por trás de um proxy de terminação TLS. Por exemplo, veja a Terminação TLS e TLS de ponta a ponta com o Gateway de Aplicativo. O HTTPS pode ser habilitado chamando builder.WebHost.UseHttpsConfiguration. O HTTP/3 pode ser habilitado chamando builder.WebHost.UseQuic.
CreateSlimBuilder
versus CreateBuilder
O método CreateSlimBuilder
não dá suporte aos seguintes recursos que têm suporte pelo método CreateBuilder
:
- Hospedando assemblies de inicialização
- UseStartup
- Os seguintes provedores de registro em log:
- Funcionalidades de hospedagem na Web:
- Configuração de Kestrel
- Restrições Regex e alfa usadas no roteamento
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
eappsettings.{EnvironmentName}.json
. - Configuração de segredos do usuário.
- Registro em log de console.
- Configuração do registro em log.
Para um construtor que omite os recursos acima, consulte O método CreateEmptyBuilder
.
A inclusão de recursos mínimos tem benefícios para filtragem, bem como AOT. Para obter mais informações, confira Cortar implantações e executáveis autocontidos.
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 o AOT nativo, o aplicativo não pode usar a reflexão desassociada em runtime. Os geradores de origem são usados para produzir código que evita a necessidade de reflexão. Em alguns casos, os geradores de origem 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 compilados. Além disso, dotnet publish
passa os assemblies gerados para um compilador de IL nativo. O compilador de IL produz o executável nativo. O executável nativo contém o código do computador nativo.
Bibliotecas e AOT nativo
Muitas das bibliotecas populares usadas em projetos do ASP.NET Core atualmente têm alguns problemas de compatibilidade quando usadas em um projeto voltado para o AOT Nativo, como:
- Uso de reflexão para inspecionar e descobrir tipos.
- Carregamento condicional de bibliotecas em runtime.
- Geração de código em tempo real para implementar a funcionalidade.
As bibliotecas que usam esses recursos dinâmicos precisam ser atualizadas para funcionar com o AOT Nativo. Elas podem ser atualizadas usando ferramentas como geradores de origem Roslyn.
Os autores da biblioteca que desejam dar suporte ao AOT nativo são incentivados a:
APIs mínimas e cargas JSON
A estrutura de API Mínima é otimizada para receber e retornar cargas JSON usando System.Text.Json. System.Text.Json
:
- Impõe requisitos de compatibilidade ao JSON e ao AOT nativo.
- Requer o uso do gerador de origem
System.Text.Json
.
Todos os tipos transmitidos como parte do corpo HTTP ou retornados de representantes 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 realçado anterior:
- O contexto do serializador JSON é registrado com o contêiner de DI. Para obter mais informações, consulte:
- O
JsonSerializerContext
personalizado é anotado com o atributo[JsonSerializable]
para habilitar o código serializador JSON gerado na origem para o tipoToDo
.
Um parâmetro no delegado que não está associado 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
Confira este problema do GitHub para relatar ou analisar problemas com o suporte do AOT nativo no ASP.NET Core.
Veja também
- Tutorial: Publicar um aplicativo ASP.NET Core usando o AOT nativo
- Implantação do AOT nativo
- Otimizar implantações AOT
- Gerador de origem para configuração da associação
- Como usar o gerador de origem do associador de configuração
- O modelo de compilação AOT de API mínima
- Comparação entre
WebApplication.CreateBuilder
eCreateSlimBuilder
- Como explorar o novo gerador de origem de API mínima
- Como substituir chamadas de método por interceptores
- Por trás de
[LogProperties]
e do novo gerador de origens de registro em log de telemetria
O ASP.NET Core 8.0 é compatível com ahead-of-time (AOT) nativo do .NET.
Razões para usar o AOT nativo com o ASP.NET Core
Publicar e implantar um aplicativo AOT nativo oferece os seguintes benefícios:
- Volume de disco minimizado: com a publicação por meio do AOT nativo, é produzido um só executável contendo apenas o código de dependências externas necessário para dar suporte ao programa. O tamanho do executável reduzido pode levar a:
- Imagens de contêiner menores, por exemplo, em cenários de implantação em contêineres.
- Tempo de implantação de imagens menores reduzido.
- Tempo de inicialização reduzido: os aplicativos AOT nativos podem mostrar tempos de inicialização reduzidos, o que significa
- Que o aplicativo está pronto para solicitações de serviço 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 executado pelo aplicativo. A redução do consumo de memória pode levar a maior densidade de implantação e escalabilidade aprimorada.
O aplicativo modelo foi executado em nosso laboratório de benchmarking para comparar o desempenho de um aplicativo publicado pelo AOT, um aplicativo de runtime filtrado e um aplicativo de runtime não filtrado. O gráfico a seguir mostra os resultados do benchmarking:
O gráfico anterior mostra que o AOT nativo tem tamanho de aplicativo, uso de memória e tempo de inicialização menores.
Compatibilidade entre o ASP.NET Core e o AOT nativo
Atualmente, nem todos os recursos do ASP.NET Core são compatíveis com o AOT nativo. A seguinte tabela resume a compatibilidade de recursos do ASP.NET Core com o AOT nativo:
Recurso | Totalmente compatível | Suporte parcial | Sem suporte |
---|---|---|---|
gRPC | Totalmente compatível | ||
APIs mínimas | Parcialmente compatível | ||
MVC | Sem suporte | ||
Blazor Server | Sem suporte | ||
SignalR | Sem suporte | ||
Autenticação JWT | Totalmente compatível | ||
Outra autenticação | Sem suporte | ||
CORS | Totalmente compatível | ||
HealthChecks | Totalmente compatível | ||
HttpLogging | Totalmente compatível | ||
Localização | Totalmente compatível | ||
OutputCaching | Totalmente compatível | ||
RateLimiting | Totalmente compatível | ||
RequestDecompression | Totalmente compatível | ||
ResponseCaching | Totalmente compatível | ||
ResponseCompression | Totalmente compatível | ||
Rewrite | Totalmente compatível | ||
Session | Sem suporte | ||
Spa | Sem suporte | ||
StaticFiles | Totalmente compatível | ||
WebSockets | Totalmente compatível |
Para obter mais informações sobre limitações, consulte:
- Limitações da implantação do AOT nativo
- Introdução aos avisos de AOT
- Incompatibilidades de corte conhecidas
- Introdução aos avisos de corte
- GitHub issue dotnet/core #8288
É importante testar um aplicativo minuciosamente ao migrar para um modelo de implantação AOT nativo. O aplicativo AOT implantado deve ser testado para verificar se a funcionalidade não foi alterada em relação ao aplicativo não filtrado e de compilação JIT. Ao compilar o aplicativo, analise e corrija os avisos AOT. Um aplicativo que emite avisos AOT durante a publicação pode não funcionar corretamente. Se nenhum aviso AOT for emitido no momento da publicação, o aplicativo AOT publicado deverá funcionar da mesma forma que o aplicativo compilado por untrimmed e JIT.
Publicação do AOT nativo
O AOT nativo está habilitado com a propriedade MSBuild PublishAot
. O seguinte exemplo mostra como habilitar o AOT nativo em um arquivo de projeto:
<PropertyGroup>
<PublishAot>true</PublishAot>
</PropertyGroup>
Essa configuração habilita a compilação AOT nativo durante a publicação e a análise dinâmica de uso de código durante o build e a edição. Um projeto que usa a publicação AOT nativo usa a compilação JIT ao ser executado localmente. Um aplicativo AOT tem as seguintes diferenças em relação a um aplicativo de compilação JIT:
- Os recursos que não são compatíveis com o AOT nativo são desabilitados e geram exceções em runtime.
- Um analisador de origem está habilitado para realçar o código que não é compatível com o AOT nativo. No momento da publicação, todo o aplicativo, incluindo pacotes NuGet, é analisado para compatibilidade novamente.
A análise AOT nativa inclui todo o código do aplicativo e as bibliotecas das quais o aplicativo depende. Leia os avisos do AOT nativo e realize as etapas corretivas. É uma boa ideia publicar aplicativos com frequência para descobrir problemas no início do ciclo de vida de desenvolvimento.
No .NET 8, o AOT nativo é compatível com os seguintes tipos de aplicativos ASP.NET Core:
- APIs mínimas: para obter mais informações, confira a seção O modelo da API Web (AOT nativo) mais adiante neste artigo.
- gRPC: para obter mais informações, confira gRPC e AOT nativo.
- Serviços de trabalho – para obter mais informações, confira AOT em modelos do Serviço de Trabalho.
O modelo de API Web (AOT nativo)
O modelo de API Web do ASP.NET Core (cujo nome curto é webapiaot
) cria um projeto com o AOT habilitado. O modelo difere do modelo de projeto da API Web 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.
- É configurado para escutar somente HTTP, pois o tráfego HTTPS geralmente é tratado por um serviço de entrada em implantações nativas de nuvem.
- Não inclui um perfil de inicialização para execução no IIS ou no IIS Express.
- Cria um arquivo
.http
configurado com solicitações HTTP de exemplo que podem ser enviadas para os pontos de extremidade do aplicativo. - Inclui uma amostra de API
Todo
em vez da amostra de previsão do tempo. - Adiciona
PublishAot
ao arquivo de projeto, conforme mostrado anteriormente neste artigo. - Habilita os geradores de origem do serializador JSON. O gerador de origem é usado para gerar um código de serialização no momento do build, o que é necessário para a compilação AOT nativo.
Alterações para dar suporte à geração de origem
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 a reflexão para serializar e desserializar o JSON. Não há suporte para reflexão no AOT nativo.
Para saber mais, veja:
Muda para launchSettings.json
O arquivo launchSettings.json
criado pelo modelo de API Web (AOT nativo) tem a seção IIS Express
e o perfil iisSettings
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 os recursos mínimos do ASP.NET Core necessários para executar um aplicativo.
Conforme observado anteriormente, o método CreateSlimBuilder
não é compatível com HTTPS ou HTTP/3. Normalmente, esses protocolos não são necessários para aplicativos executados por trás de um proxy de terminação TLS. Por exemplo, veja a Terminação TLS e TLS de ponta a ponta com o Gateway de Aplicativo. O HTTPS pode ser habilitado chamando builder.WebHost.UseHttpsConfiguration. O HTTP/3 pode ser habilitado chamando builder.WebHost.UseQuic.
CreateSlimBuilder
versus CreateBuilder
O método CreateSlimBuilder
não dá suporte aos seguintes recursos que têm suporte pelo método CreateBuilder
:
- Hospedando assemblies de inicialização
- UseStartup
- Os seguintes provedores de registro em log:
- Funcionalidades de hospedagem na Web:
- Configuração de Kestrel
- Restrições Regex e alfa usadas no roteamento
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
eappsettings.{EnvironmentName}.json
. - Configuração de segredos do usuário.
- Registro em log de console.
- Configuração do registro em log.
Para um construtor que omite os recursos acima, consulte O método CreateEmptyBuilder
.
A inclusão de recursos mínimos tem benefícios para filtragem, bem como AOT. Para obter mais informações, confira Cortar implantações e executáveis autocontidos.
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 o AOT nativo, o aplicativo não pode usar a reflexão desassociada em runtime. Os geradores de origem são usados para produzir código que evita a necessidade de reflexão. Em alguns casos, os geradores de origem 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 compilados. Além disso, dotnet publish
passa os assemblies gerados para um compilador de IL nativo. O compilador de IL produz o executável nativo. O executável nativo contém o código do computador nativo.
Bibliotecas e AOT nativo
Muitas das bibliotecas populares usadas em projetos do ASP.NET Core atualmente têm alguns problemas de compatibilidade quando usadas em um projeto voltado para o AOT Nativo, como:
- Uso de reflexão para inspecionar e descobrir tipos.
- Carregamento condicional de bibliotecas em runtime.
- Geração de código em tempo real para implementar a funcionalidade.
As bibliotecas que usam esses recursos dinâmicos precisam ser atualizadas para funcionar com o AOT Nativo. Elas podem ser atualizadas usando ferramentas como geradores de origem Roslyn.
Os autores da biblioteca que desejam dar suporte ao AOT nativo são incentivados a:
APIs mínimas e cargas JSON
A estrutura de API Mínima é otimizada para receber e retornar cargas JSON usando System.Text.Json. System.Text.Json
:
- Impõe requisitos de compatibilidade ao JSON e ao AOT nativo.
- Requer o uso do gerador de origem
System.Text.Json
.
Todos os tipos transmitidos como parte do corpo HTTP ou retornados de representantes 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 realçado anterior:
- O contexto do serializador JSON é registrado com o contêiner de DI. Para obter mais informações, consulte:
- O
JsonSerializerContext
personalizado é anotado com o atributo[JsonSerializable]
para habilitar o código serializador JSON gerado na origem para o tipoToDo
.
Um parâmetro no delegado que não está associado 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
Confira este problema do GitHub para relatar ou analisar problemas com o suporte do AOT nativo no ASP.NET Core.
Veja também
- Tutorial: Publicar um aplicativo ASP.NET Core usando o AOT nativo
- Implantação do AOT nativo
- Otimizar implantações AOT
- Gerador de origem para configuração da associação
- Como usar o gerador de origem do associador de configuração
- O modelo de compilação AOT de API mínima
- Comparação entre
WebApplication.CreateBuilder
eCreateSlimBuilder
- Como explorar o novo gerador de origem de API mínima
- Como substituir chamadas de método por interceptores
- Por trás de
[LogProperties]
e do novo gerador de origens de registro em log de telemetria