--- title: ASP.NET Core support for Native AOT author: rick-anderson ms.author: riande description: Learn about ASP.NET Core support for Native AOT content_well_notification: AI-contribution ms.custom: mvc, engagement-fy23 ms.date: 8/11/2024 uid: fundamentals/native-aot ai-usage: ai-assisted --- # ASP.NET Core support for Native AOT By [Mitch Denny](https://github.com/mitchdenny) :::moniker range=">= aspnetcore-9.0" ASP.NET Core 8.0 introduces support for [.NET native ahead-of-time (AOT)](/dotnet/core/deploying/native-aot/). For Blazor WebAssembly Native AOT guidance, which adds to or supersedes the guidance in this article, see . ## Why use Native AOT with ASP.NET Core Publishing and deploying a Native AOT app provides the following benefits: * **Minimized disk footprint**: When publishing using Native AOT, a single executable is produced containing just the code from external dependencies that is needed to support the program. Reduced executable size can lead to: * Smaller container images, for example in containerized deployment scenarios. * Reduced deployment time from smaller images. * **Reduced startup time**: Native AOT applications can show reduced start-up times, which means * The app is ready to service requests quicker. * Improved deployment where container orchestrators need to manage transition from one version of the app to another. * **Reduced memory demand**: Native AOT apps can have reduced memory demands, depending on the work done by the app. Reduced memory consumption can lead to greater deployment density and improved scalability. The template app was run in our benchmarking lab to compare performance of an AOT published app, a trimmed runtime app, and an untrimmed runtime app. The following chart shows the results of the benchmarking: ![Chart showing comparison of application size, memory use, and startup time metrics of an AOT published app, a runtime app that is trimmed, and an untrimmed runtime app.](~/fundamentals/aot/_static/aot-runtime-trimmed-perf-chart.png) The preceding chart shows that Native AOT has lower app size, memory usage, and startup time. ## ASP.NET Core and Native AOT compatibility Not all features in ASP.NET Core are currently compatible with Native AOT. The following table summarizes ASP.NET Core feature compatibility with Native AOT: | Feature | Fully Supported | Partially Supported | Not Supported | | - | - | - | - | | gRPC | Fully supported | | | | Minimal APIs | | Partially supported | | | MVC | | | Not supported | | Blazor Server | | |Not supported | | SignalR | | Partially supported | | | JWT Authentication | Fully supported | | | | Other Authentication | | | Not supported | | CORS | Fully supported | | | | HealthChecks | Fully supported | | | | HttpLogging | Fully supported | | | | Localization | Fully supported | | | | OutputCaching | Fully supported | | | | RateLimiting | Fully supported | | | | RequestDecompression | Fully supported | | | | ResponseCaching | Fully supported | | | | ResponseCompression | Fully supported | | | | Rewrite | Fully supported | | | | Session | | |Not supported | | Spa | | |Not supported | | StaticFiles | Fully supported | | | | WebSockets | Fully supported | | | For more information on limitations, see: * [Limitations of Native AOT deployment](/dotnet/core/deploying/native-aot#limitations-of-native-aot-deployment) * [Introduction to AOT warnings](/dotnet/core/deploying/native-aot/fixing-warnings) * [Known trimming incompatibilities](/dotnet/core/deploying/trimming/incompatibilities) * [Introduction to trim warnings](/dotnet/core/deploying/trimming/fixing-warnings) * [GitHub issue dotnet/core #8288](https://github.com/dotnet/core/issues/8288) It's important to test an app thoroughly when moving to a Native AOT deployment model. The AOT deployed app should be tested to verify functionality hasn't changed from the untrimmed and JIT-compiled app. When building the app, review and correct AOT warnings. An app that issues [AOT warnings](/dotnet/core/deploying/trimming/fixing-warnings) during publishing may not work correctly. If no AOT warnings are issued at publish time, the published AOT app should work the same as the untrimmed and JIT-compiled app. ## Native AOT publishing Native AOT is enabled with the `PublishAot` MSBuild property. The following example shows how to enable Native AOT in a project file: ```xml true ``` This setting enables Native AOT compilation during publish and enables dynamic code usage analysis during build and editing. A project that uses Native AOT publishing uses JIT compilation when running locally. An AOT app has the following differences from a JIT-compiled app: * Features that aren't compatible with Native AOT are disabled and throw exceptions at run time. * A source analyzer is enabled to highlight code that isn't compatible with Native AOT. At publish time, the entire app, including NuGet packages, are analyzed for compatibility again. Native AOT analysis includes all of the app's code and the libraries the app depends on. Review Native AOT warnings and take corrective steps. It's a good idea to publish apps frequently to discover issues early in the development lifecycle. In .NET 8, Native AOT is supported by the following ASP.NET Core app types: * minimal APIs - For more information, see the [The Web API (Native AOT) template](#the-web-api-native-aot-template) section later in this article. * gRPC - For more information, see [gRPC and Native AOT](xref:grpc/native-aot). * Worker services - For more information, see [AOT in Worker Service templates](xref:fundamentals/host/hosted-services?view=aspnetcore-8.0&preserve-view=true#native-aot). ## The Web API (Native AOT) template The **ASP.NET Core Web API (Native AOT)** template (short name `webapiaot`) creates a project with AOT enabled. The template differs from the **Web API** project template in the following ways: * Uses minimal APIs only, as MVC isn't yet compatible with Native AOT. * Uses the API to ensure only the essential features are enabled by default, minimizing the app's deployed size. * Is configured to listen on HTTP only, as HTTPS traffic is commonly handled by an ingress service in cloud-native deployments. * Doesn't include a launch profile for running under IIS or IIS Express. * Creates an [`.http` file](xref:test/http-files) configured with sample HTTP requests that can be sent to the app's endpoints. * Includes a sample `Todo` API instead of the weather forecast sample. * Adds `PublishAot` to the project file, as shown [earlier in this article](#native-aot-publishing). * Enables the [JSON serializer source generators](/dotnet/standard/serialization/system-text-json/source-generation). The source generator is used to generate serialization code at build time, which is required for Native AOT compilation. ### Changes to support source generation The following example shows the code added to the `Program.cs` file to support JSON serialization source generation: ```diff 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 +{ + +} ``` Without this added code, `System.Text.Json` uses reflection to serialize and deserialize JSON. Reflection isn't supported in Native AOT. For more information, see: * [Combine source generators](/dotnet/standard/serialization/system-text-json/source-generation?pivots=dotnet-8-0#combine-source-generators) * ### Changes to `launchSettings.json` The `launchSettings.json` file created by the **Web API (Native AOT)** template has the `iisSettings` section and `IIS Express` profile removed: ```diff { "$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" - } - } } } ``` ### The `CreateSlimBuilder` method The template uses the method instead of the method. :::code language="csharp" source="~/fundamentals/aot/samples/Program.cs" highlight="4"::: The `CreateSlimBuilder` method initializes the with the minimum ASP.NET Core features necessary to run an app. As noted earlier, the `CreateSlimBuilder` method doesn't include support for HTTPS or HTTP/3. These protocols typically aren't required for apps that run behind a TLS termination proxy. For example, see [TLS termination and end to end TLS with Application Gateway](/azure/application-gateway/ssl-overview). HTTPS can be enabled by calling [builder.WebHost.UseKestrelHttpsConfiguration](https://source.dot.net/#Microsoft.AspNetCore.Server.Kestrel/WebHostBuilderKestrelExtensions.cs,fcec859000ccaa50) HTTP/3 can be enabled by calling [builder.WebHost.UseQuic](xref:Microsoft.AspNetCore.Hosting.WebHostBuilderQuicExtensions.UseQuic%2A). ### `CreateSlimBuilder` vs `CreateBuilder` The `CreateSlimBuilder` method doesn't support the following features that are supported by the `CreateBuilder` method: * [Hosting startup assemblies](xref:fundamentals/configuration/platform-specific-configuration) * * The following logging providers: * [Windows EventLog](/aspnet/core/fundamentals/logging#windows-eventlog) * [Debug](/aspnet/core/fundamentals/logging#debug) * [Event Source](/aspnet/core/fundamentals/logging#event-source) * Web hosting features: * * [IIS Integration](xref:host-and-deploy/iis/index) * Kestrel configuration * [HTTPS endpoints in Kestrel](xref:fundamentals/servers/kestrel/endpoints#https) * [Quic (HTTP/3)](xref:fundamentals/servers/kestrel/http3#http3-benefits) * [Regex and alpha constraints used in routing](https://github.com/dotnet/aspnetcore/issues/46142) The `CreateSlimBuilder` method includes the following features needed for an efficient development experience: * JSON file configuration for `appsettings.json` and `appsettings.{EnvironmentName}.json`. * User secrets configuration. * Console logging. * Logging configuration. For a builder that omits the preceding features, see [The `CreateEmptyBuilder` method](xref:aspnetcore-8#new-createemptybuilder-method). Including minimal features has benefits for trimming as well as AOT. For more information, see [Trim self-contained deployments and executables](/dotnet/core/deploying/trimming/trim-self-contained). For more detailed information, see [Comparing `WebApplication.CreateBuilder` to `CreateSlimBuilder`](https://andrewlock.net/exploring-the-dotnet-8-preview-comparing-createbuilder-to-the-new-createslimbuilder-method/) ## Source generators Because unused code is trimmed during publishing for Native AOT, the app can't use unbounded reflection at runtime. [Source generators](/dotnet/csharp/roslyn-sdk/source-generators-overview) are used to produce code that avoids the need for reflection. In some cases, source generators produce code optimized for AOT even when a generator isn't required. To view the source code that is generated, add the [`EmitCompilerGeneratedFiles`](/dotnet/csharp/roslyn-sdk/source-generators-overview) property to an app's `.csproj` file, as shown in the following example: ```xml true ``` Run the `dotnet build` command to see the generated code. The output includes an `obj/Debug/net8.0/generated/` directory that contains all the generated files for the project. The `dotnet publish` command also compiles the source files and generates files that are compiled. In addition, `dotnet publish` passes the generated assemblies to a native IL compiler. The IL compiler produces the native executable. The native executable contains the native machine code. [!INCLUDE[](~/fundamentals/aot/includes/aot_lib.md)] ## Minimal APIs and JSON payloads The Minimal API framework is optimized for receiving and returning JSON payloads using . `System.Text.Json`: * Imposes compatibility requirements for JSON and Native AOT. * Requires the use of the [`System.Text.Json` source generator](/dotnet/standard/serialization/system-text-json/source-generation). All types that are transmitted as part of the HTTP body or returned from request delegates in Minimal APIs apps must be configured on a that is registered via ASP.NET Core’s dependency injection: :::code language="csharp" source="~/fundamentals/aot/samples/Program.cs" highlight="7-10,25-99"::: In the preceding highlighted code: * The JSON serializer context is registered with the [DI container](xref:fundamentals/dependency-injection). For more information, see: * [Combine source generators](/dotnet/standard/serialization/system-text-json/source-generation?pivots=dotnet-8-0#combine-source-generators) * * The custom `JsonSerializerContext` is annotated with the [`[JsonSerializable]`](/dotnet/api/system.text.json.serialization.jsonserializableattribute) attribute to enable source generated JSON serializer code for the `ToDo` type. A parameter on the delegate that isn't bound to the body and does ***not*** need to be serializable. For example, a query string parameter that is a rich object type and implements `IParsable`. :::code language="csharp" source="~/fundamentals/aot/samples/Todo.cs" id="snippet_1"::: ## Known issues See [this GitHub issue](https://github.com/dotnet/core/issues/8288) to report or review issues with Native AOT support in ASP.NET Core. ## See also * * [Native AOT deployment](/dotnet/core/deploying/native-aot/) * [Optimize AOT deployments](/dotnet/core/deploying/native-aot/optimizing) * [Configuration-binding source generator](/dotnet/core/whats-new/dotnet-8#configuration-binding-source-generator) * [Using the configuration binder source generator](https://andrewlock.net/exploring-the-dotnet-8-preview-using-the-new-configuration-binder-source-generator/) * [The minimal API AOT compilation template](https://andrewlock.net/exploring-the-dotnet-8-preview-the-minimal-api-aot-template/) * [Comparing `WebApplication.CreateBuilder` to `CreateSlimBuilder`](https://andrewlock.net/exploring-the-dotnet-8-preview-comparing-createbuilder-to-the-new-createslimbuilder-method/) * [Exploring the new minimal API source generator](https://andrewlock.net/exploring-the-dotnet-8-preview-exploring-the-new-minimal-api-source-generator/) * [Replacing method calls with Interceptors](https://andrewlock.net/exploring-the-dotnet-8-preview-changing-method-calls-with-interceptors/) * [Behind `[LogProperties]` and the new telemetry logging source generator](https://andrewlock.net/behind-logproperties-and-the-new-telemetry-logging-source-generator/) :::moniker-end [!INCLUDE[](~/fundamentals/native-aot/includes/native-aot8.md)]