Udostępnij za pośrednictwem


obsługa platformy ASP.NET Core dla natywnej usługi AOT

Autor: Mitch Denny

Aby zapoznać się ze wskazówkami dotyczącymi natywnej kompilacji AOT, które dodają lub zastępują wskazówki zawarte w tym artykule, zobacz Blazor WebAssembly.

Dlaczego warto używać natywnej AOT z platformą ASP.NET Core

Publikowanie i wdrażanie natywnej aplikacji AOT zapewnia następujące korzyści:

  • Zminimalizowane zużycie dysku: podczas publikowania przy użyciu natywnej funkcji AOT jest tworzony pojedynczy plik wykonywalny zawierający tylko kod z zależności zewnętrznych, które są potrzebne do obsługi programu. Zmniejszony rozmiar pliku wykonywalnego może prowadzić do:
    • Mniejsze obrazy kontenerów, na przykład w scenariuszach wdrażania konteneryzowanego.
    • Skrócony czas wdrażania dzięki mniejszym obrazom.
  • Skrócony czas uruchamiania: natywne aplikacje AOT mogą pokazywać skrócone czasy uruchamiania, co oznacza
    • Aplikacja jest gotowa do szybszego obsługi żądań.
    • Ulepszone wdrożenie, w którym koordynatorzy kontenerów muszą zarządzać przejściem z jednej wersji aplikacji do innej.
  • Mniejsze zapotrzebowanie na pamięć: natywne aplikacje AOT mogą mieć mniejsze zapotrzebowanie na pamięć w zależności od pracy wykonywanej przez aplikację. Zmniejszenie zużycia pamięci może prowadzić do większej gęstości wdrożenia i zwiększenia skalowalności.

Aplikacja szablonu została uruchomiona w naszym laboratorium porównawczym, aby porównać wydajność aplikacji opublikowanej w trybie AOT, aplikacji wykonanej w przyciętym środowisku uruchomieniowym i aplikacji wykonanej w nieprzyciętym środowisku uruchomieniowym. Na poniższym wykresie przedstawiono wyniki testów porównawczych:

Wykres przedstawiający porównanie metryk rozmiaru aplikacji, użycia pamięci i czasu uruchamiania aplikacji opublikowanej z użyciem AOT, przycinanej aplikacji środowiska uruchomieniowego oraz nieskracanej aplikacji środowiska uruchomieniowego.

Na poprzednim wykresie pokazano, że natywna usługa AOT ma mniejszy rozmiar aplikacji, użycie pamięci i czas uruchamiania.

Kompatybilność ASP.NET Core i Native AOT

Nie wszystkie funkcje w systemie ASP.NET Core są obecnie zgodne z natywną funkcją AOT. Poniższa tabela zawiera podsumowanie zgodności funkcji ASP.NET Core z natywną funkcją AOT:

Funkcja W pełni obsługiwane Częściowo wspierane Nie jest obsługiwany
gRPC W pełni obsługiwane
Minimalne API Częściowo obsługiwane
MVC Nieobsługiwane
Blazor Server Nieobsługiwane
SignalR Częściowo obsługiwane
Uwierzytelnianie JWT W pełni obsługiwane
Inne uwierzytelnianie Nieobsługiwane
CORS (Cross-Origin Resource Sharing) W pełni obsługiwane
Kontrole kondycji W pełni obsługiwane
Logowanie HTTP W pełni obsługiwane
Lokalizacja W pełni obsługiwane
OutputCaching W pełni obsługiwane
Ograniczanie częstotliwości W pełni obsługiwane
Żądanie dekompresji W pełni obsługiwane
BuforowanieOdpowiedzi W pełni obsługiwane
Kompresja odpowiedzi W pełni obsługiwane
Przepisać W pełni obsługiwane
Sesja Nieobsługiwane
Uzdrowisko Nieobsługiwane
StaticFiles W pełni obsługiwane
WebSocket W pełni obsługiwane

Aby uzyskać więcej informacji na temat ograniczeń, zobacz:

Ważne jest, aby dokładnie przetestować aplikację podczas przechodzenia do natywnego modelu wdrażania AOT. Aplikacja AOT wdrożona powinna zostać przetestowana w celu sprawdzenia, czy funkcjonalność pozostała niezmieniona w porównaniu do nietrimowanej i skompilowanej za pomocą JIT aplikacji. Podczas kompilowania aplikacji przejrzyj i popraw ostrzeżenia dotyczące AOT. Aplikacja, która wystawia ostrzeżenia AOT podczas publikowania, może nie działać poprawnie. Jeśli w czasie publikowania nie zostaną wydane żadne ostrzeżenia dotyczące funkcji AOT, opublikowana aplikacja AOT powinna działać tak samo jak aplikacja nieskrócona i skompilowana za pomocą JIT.

Publikowanie natywne AOT

Natywna funkcja AOT jest włączona z właściwością PublishAot MSBuild. W poniższym przykładzie pokazano, jak włączyć natywną funkcję AOT w pliku projektu:

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

To ustawienie umożliwia natywną kompilację AOT podczas publikowania i umożliwia dynamiczną analizę użycia kodu podczas kompilacji i edycji. Projekt korzystający z natywnego publikowania AOT używa kompilacji JIT podczas uruchamiania lokalnego. Aplikacja AOT ma następujące różnice w porównaniu z aplikacją skompilowana w trybie JIT:

  • Cechy, które nie są zgodne z natywnym AOT, są wyłączane i zgłaszają wyjątki w czasie działania programu.
  • Analizator źródła został włączony, aby wyróżnić kod, który nie jest zgodny z Native AOT. W czasie publikowania cała aplikacja, w tym pakiety NuGet, jest ponownie analizowana pod kątem zgodności.

Natywna analiza AOT obejmuje cały kod aplikacji i biblioteki, od których zależy aplikacja. Przejrzyj ostrzeżenia dotyczące natywnej usługi AOT i wykonaj kroki naprawcze. Dobrym pomysłem jest częste publikowanie aplikacji w celu wykrycia problemów na wczesnym etapie cyklu projektowania.

Na platformie .NET 8 natywna funkcja AOT jest obsługiwana przez następujące typy aplikacji ASP.NET Core:

Szablon interfejsu API sieci Web (natywne AOT)

Szablon ASP.NET Core Web API (Native AOT) (krótkie oznaczenie webapiaot) tworzy projekt z włączoną funkcją AOT. Szablon różni się od szablonu projektu Web API w następujący sposób:

  • Używa tylko minimalnych interfejsów API, ponieważ MVC nie jest jeszcze zgodne z natywnym AOT.
  • Używa interfejsu CreateSlimBuilder() API, aby upewnić się, że tylko podstawowe funkcje są domyślnie włączone, minimalizując rozmiar wdrożonej aplikacji.
  • Jest skonfigurowany do nasłuchiwania tylko w protokole HTTP, ponieważ ruch HTTPS jest często obsługiwany przez usługę ruchu przychodzącego we wdrożeniach natywnych dla chmury.
  • Nie zawiera profilu uruchamiania do działania w środowiskach IIS lub IIS Express.
  • .http Tworzy plik skonfigurowany przy użyciu przykładowych żądań HTTP, które można wysyłać do punktów końcowych aplikacji.
  • Zawiera przykładowy interfejs API Todo zamiast przykładowej prognozy pogody.
  • Dodaje PublishAot do pliku projektu, jak pokazano wcześniej w tym artykule.
  • Włącza generatory źródłowe serializatora JSON. Generator źródła służy do generowania kodu serializacji w czasie kompilacji, który jest wymagany do kompilacji natywnej AOT.

Zmiany w zakresie obsługi generowania kodu źródłowego

W poniższym przykładzie pokazano kod dodany do Program.cs pliku w celu obsługi generowania źródła serializacji 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
+{
+
+}

Bez tego dodanego kodu System.Text.Json używa refleksji w celu serializacji i deserializacji JSON. Refleksja nie jest obsługiwana w natywnej AOT.

Aby uzyskać więcej informacji, zobacz:

Zmiany do launchSettings.json

Plik launchSettings.json utworzony przez szablon Web API (natywny AOT) ma usuniętą sekcję iisSettings oraz profil IIS Express.

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

Metoda CreateSlimBuilder

Szablon używa CreateSlimBuilder() metody zamiast CreateBuilder() metody .

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

Metoda CreateSlimBuilder inicjuje WebApplicationBuilder z minimalnym zestawem funkcji ASP.NET Core niezbędnymi do uruchomienia aplikacji.

Jak wspomniano wcześniej, CreateSlimBuilder metoda nie obejmuje obsługi protokołu HTTPS lub HTTP/3. Te protokoły zazwyczaj nie są wymagane w przypadku aplikacji uruchamianych za serwerem proxy zakończenia protokołu TLS. Zobacz na przykład terminację TLS i szyfrowanie TLS typu end-to-end za pomocą usługi Application Gateway. Protokół HTTPS można włączyć, wywołując konstruktora builder.WebHost.UseKestrelHttpsConfiguration. Protokół HTTP/3 można włączyć, wywołując konstruktora builder.WebHost.UseQuic.

Klasa CreateSlimBuilder a klasa CreateBuilder

Metoda CreateSlimBuilder nie obsługuje następujących funkcji obsługiwanych przez metodę CreateBuilder :

Metoda CreateSlimBuilder zawiera następujące funkcje potrzebne do wydajnego środowiska programistycznego:

  • Konfiguracja pliku JSON dla elementów appsettings.json i appsettings.{EnvironmentName}.json.
  • Konfiguracja tajnych danych użytkownika.
  • Logowanie konsoli.
  • Konfiguracja rejestrowania.

Aby zapoznać się z narzędziem budowania, które pomija wcześniejsze funkcjonalności, zobacz Metoda CreateEmptyBuilder.

Uwzględnienie minimalnych funkcji przynosi korzyści dla przycinania oraz AOT. Aby uzyskać więcej informacji, zobacz Przycinanie samodzielnych wdrożeń i plików wykonywalnych.

Aby uzyskać bardziej szczegółowe informacje, zobacz Porównanie WebApplication.CreateBuilder z CreateSlimBuilder

Generatory źródeł

Ponieważ nieużywany kod jest usuwany podczas publikowania w kontekście natywnego AOT, aplikacja nie może używać nieograniczonego odbicia w czasie wykonywania. Generatory źródeł są używane do tworzenia kodu, który pozwala uniknąć konieczności odbicia. W niektórych przypadkach generatory źródłowe generują kod zoptymalizowany pod kątem AOT nawet wtedy, gdy generator nie jest wymagany.

Aby wyświetlić wygenerowany kod źródłowy, dodaj właściwość EmitCompilerGeneratedFiles do pliku .csproj aplikacji, jak pokazano w poniższym przykładzie.

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

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

</Project>

Uruchom polecenie , dotnet build aby wyświetlić wygenerowany kod. Dane wyjściowe zawierają obj/Debug/net8.0/generated/ katalog zawierający wszystkie wygenerowane pliki dla projektu.

Polecenie dotnet publish kompiluje również pliki źródłowe i generuje skompilowane pliki. Ponadto dotnet publish przekazuje wygenerowane zestawy do natywnego kompilatora IL. Kompilator IL tworzy natywny plik wykonywalny. Natywny plik wykonywalny zawiera natywny kod maszyny.

Biblioteki i natywna usługa AOT

Wiele popularnych bibliotek używanych w projektach ASP.NET Core ma obecnie pewne problemy ze zgodnością w przypadku użycia w projekcie przeznaczonym dla natywnej funkcji AOT, takich jak:

  • Używanie odbicia do sprawdzania i odnajdywania typów.
  • Warunkowe ładowanie bibliotek w czasie wykonywania.
  • Generowanie kodu na bieżąco w celu zaimplementowania funkcji.

Biblioteki korzystające z tych funkcji dynamicznych należy zaktualizować w celu pracy z natywną usługą AOT. Można je aktualizować przy użyciu narzędzi, takich jak generatory źródeł Roslyn.

Autorzy bibliotek, którzy mają nadzieję obsługiwać natywne AOT, są zachęcani do:

Minimalne interfejsy API i ładunki JSON

Minimalna struktura interfejsu API jest zoptymalizowana pod kątem odbierania i zwracania ładunków JSON przy użyciu polecenia System.Text.Json. System.Text.Json:

  • Nakłada wymagania dotyczące zgodności dla formatu JSON i natywnego AOT.
  • Wymaga użycia generatora źródeł System.Text.Json.

Wszystkie typy przesyłane jako część treści HTTP lub zwracane z delegatów żądań w aplikacjach minimalnych interfejsów API muszą być skonfigurowane na obiekcie JsonSerializerContext , który jest zarejestrowany za pośrednictwem wstrzykiwania zależności 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
{
}

W poprzednim wyróżnionym kodzie:

Parametr delegata, który nie jest powiązany z treścią i nie musi być serializowalny. Na przykład parametr ciągu zapytania, który jest bogatym typem obiektu i implementuje element 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.

Znane problemy

Zobacz to zadanie GitHub, aby zgłosić lub przejrzeć problemy z natywną obsługą Native AOT w ASP.NET Core.

Zobacz też

Platforma .NET 8 wprowadza obsługę natywnej kompilacji .NET wykonywanej z wyprzedzeniem (AOT).

Dlaczego warto używać natywnej AOT z platformą ASP.NET Core

Publikowanie i wdrażanie natywnej aplikacji AOT zapewnia następujące korzyści:

  • Zminimalizowane zużycie dysku: podczas publikowania przy użyciu natywnej funkcji AOT jest tworzony pojedynczy plik wykonywalny zawierający tylko kod z zależności zewnętrznych, które są potrzebne do obsługi programu. Zmniejszony rozmiar pliku wykonywalnego może prowadzić do:
    • Mniejsze obrazy kontenerów, na przykład w scenariuszach wdrażania konteneryzowanego.
    • Skrócony czas wdrażania dzięki mniejszym obrazom.
  • Skrócony czas uruchamiania: natywne aplikacje AOT mogą pokazywać skrócone czasy uruchamiania, co oznacza
    • Aplikacja jest gotowa do szybszego obsługi żądań.
    • Ulepszone wdrożenie, w którym koordynatorzy kontenerów muszą zarządzać przejściem z jednej wersji aplikacji do innej.
  • Mniejsze zapotrzebowanie na pamięć: natywne aplikacje AOT mogą mieć mniejsze zapotrzebowanie na pamięć w zależności od pracy wykonywanej przez aplikację. Zmniejszenie zużycia pamięci może prowadzić do większej gęstości wdrożenia i zwiększenia skalowalności.

Aplikacja szablonu została uruchomiona w naszym laboratorium porównawczym, aby porównać wydajność aplikacji opublikowanej w trybie AOT, aplikacji wykonanej w przyciętym środowisku uruchomieniowym i aplikacji wykonanej w nieprzyciętym środowisku uruchomieniowym. Na poniższym wykresie przedstawiono wyniki testów porównawczych:

Wykres przedstawiający porównanie metryk rozmiaru aplikacji, użycia pamięci i czasu uruchamiania aplikacji opublikowanej z użyciem AOT, przycinanej aplikacji środowiska uruchomieniowego oraz nieskracanej aplikacji środowiska uruchomieniowego.

Na poprzednim wykresie pokazano, że natywna usługa AOT ma mniejszy rozmiar aplikacji, użycie pamięci i czas uruchamiania.

Kompatybilność ASP.NET Core i Native AOT

Nie wszystkie funkcje w systemie ASP.NET Core są obecnie zgodne z natywną funkcją AOT. Poniższa tabela zawiera podsumowanie zgodności funkcji ASP.NET Core z natywną funkcją AOT:

Funkcja W pełni obsługiwane Częściowo wspierane Nie jest obsługiwany
gRPC W pełni obsługiwane
Minimalne API Częściowo obsługiwane
MVC Nieobsługiwane
Blazor Server Nieobsługiwane
SignalR Nieobsługiwane
Uwierzytelnianie JWT W pełni obsługiwane
Inne uwierzytelnianie Nieobsługiwane
CORS (Cross-Origin Resource Sharing) W pełni obsługiwane
Kontrole kondycji W pełni obsługiwane
Logowanie HTTP W pełni obsługiwane
Lokalizacja W pełni obsługiwane
OutputCaching W pełni obsługiwane
Ograniczanie częstotliwości W pełni obsługiwane
Żądanie dekompresji W pełni obsługiwane
BuforowanieOdpowiedzi W pełni obsługiwane
Kompresja odpowiedzi W pełni obsługiwane
Przepisać W pełni obsługiwane
Sesja Nieobsługiwane
Uzdrowisko Nieobsługiwane
StaticFiles W pełni obsługiwane
WebSocket W pełni obsługiwane

Aby uzyskać więcej informacji na temat ograniczeń, zobacz:

Ważne jest, aby dokładnie przetestować aplikację podczas przechodzenia do natywnego modelu wdrażania AOT. Aplikacja AOT wdrożona powinna zostać przetestowana w celu sprawdzenia, czy funkcjonalność pozostała niezmieniona w porównaniu do nietrimowanej i skompilowanej za pomocą JIT aplikacji. Podczas kompilowania aplikacji przejrzyj i popraw ostrzeżenia dotyczące AOT. Aplikacja, która wystawia ostrzeżenia AOT podczas publikowania, może nie działać poprawnie. Jeśli w czasie publikowania nie zostaną wydane żadne ostrzeżenia dotyczące funkcji AOT, opublikowana aplikacja AOT powinna działać tak samo jak aplikacja nieskrócona i skompilowana za pomocą JIT.

Publikowanie natywne AOT

Natywna funkcja AOT jest włączona z właściwością PublishAot MSBuild. W poniższym przykładzie pokazano, jak włączyć natywną funkcję AOT w pliku projektu:

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

To ustawienie umożliwia natywną kompilację AOT podczas publikowania i umożliwia dynamiczną analizę użycia kodu podczas kompilacji i edycji. Projekt korzystający z natywnego publikowania AOT używa kompilacji JIT podczas uruchamiania lokalnego. Aplikacja AOT ma następujące różnice w porównaniu z aplikacją skompilowana w trybie JIT:

  • Cechy, które nie są zgodne z natywnym AOT, są wyłączane i zgłaszają wyjątki w czasie działania programu.
  • Analizator źródła został włączony, aby wyróżnić kod, który nie jest zgodny z Native AOT. W czasie publikowania cała aplikacja, w tym pakiety NuGet, jest ponownie analizowana pod kątem zgodności.

Natywna analiza AOT obejmuje cały kod aplikacji i biblioteki, od których zależy aplikacja. Przejrzyj ostrzeżenia dotyczące natywnej usługi AOT i wykonaj kroki naprawcze. Dobrym pomysłem jest częste publikowanie aplikacji w celu wykrycia problemów na wczesnym etapie cyklu projektowania.

Na platformie .NET 8 natywna funkcja AOT jest obsługiwana przez następujące typy aplikacji ASP.NET Core:

Szablon interfejsu API sieci Web (natywne AOT)

Szablon ASP.NET Core Web API (Native AOT) (krótkie oznaczenie webapiaot) tworzy projekt z włączoną funkcją AOT. Szablon różni się od szablonu projektu Web API w następujący sposób:

  • Używa tylko minimalnych interfejsów API, ponieważ MVC nie jest jeszcze zgodne z natywnym AOT.
  • Używa interfejsu CreateSlimBuilder() API, aby upewnić się, że tylko podstawowe funkcje są domyślnie włączone, minimalizując rozmiar wdrożonej aplikacji.
  • Jest skonfigurowany do nasłuchiwania tylko w protokole HTTP, ponieważ ruch HTTPS jest często obsługiwany przez usługę ruchu przychodzącego we wdrożeniach natywnych dla chmury.
  • Nie zawiera profilu uruchamiania do działania w środowiskach IIS lub IIS Express.
  • .http Tworzy plik skonfigurowany przy użyciu przykładowych żądań HTTP, które można wysyłać do punktów końcowych aplikacji.
  • Zawiera przykładowy interfejs API Todo zamiast przykładowej prognozy pogody.
  • Dodaje PublishAot do pliku projektu, jak pokazano wcześniej w tym artykule.
  • Włącza generatory źródłowe serializatora JSON. Generator źródła służy do generowania kodu serializacji w czasie kompilacji, który jest wymagany do kompilacji natywnej AOT.

Zmiany w zakresie obsługi generowania kodu źródłowego

W poniższym przykładzie pokazano kod dodany do Program.cs pliku w celu obsługi generowania źródła serializacji 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
+{
+
+}

Bez tego dodanego kodu System.Text.Json używa refleksji w celu serializacji i deserializacji JSON. Refleksja nie jest obsługiwana w natywnej AOT.

Aby uzyskać więcej informacji, zobacz:

Zmiany do launchSettings.json

Plik launchSettings.json utworzony przez szablon Web API (natywny AOT) ma usuniętą sekcję iisSettings oraz profil IIS Express.

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

Metoda CreateSlimBuilder

Szablon używa CreateSlimBuilder() metody zamiast CreateBuilder() metody .

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

Metoda CreateSlimBuilder inicjuje WebApplicationBuilder z minimalnym zestawem funkcji ASP.NET Core niezbędnymi do uruchomienia aplikacji.

Jak wspomniano wcześniej, CreateSlimBuilder metoda nie obejmuje obsługi protokołu HTTPS lub HTTP/3. Te protokoły zazwyczaj nie są wymagane w przypadku aplikacji uruchamianych za serwerem proxy zakończenia protokołu TLS. Zobacz na przykład terminację TLS i szyfrowanie TLS typu end-to-end za pomocą usługi Application Gateway. Protokół HTTPS można włączyć, wywołując konstruktora builder.WebHost.UseKestrelHttpsConfiguration. Protokół HTTP/3 można włączyć, wywołując konstruktora builder.WebHost.UseQuic.

Klasa CreateSlimBuilder a klasa CreateBuilder

Metoda CreateSlimBuilder nie obsługuje następujących funkcji obsługiwanych przez metodę CreateBuilder :

Metoda CreateSlimBuilder zawiera następujące funkcje potrzebne do wydajnego środowiska programistycznego:

  • Konfiguracja pliku JSON dla elementów appsettings.json i appsettings.{EnvironmentName}.json.
  • Konfiguracja tajnych danych użytkownika.
  • Logowanie konsoli.
  • Konfiguracja rejestrowania.

Aby zapoznać się z narzędziem budowania, które pomija wcześniejsze funkcjonalności, zobacz Metoda CreateEmptyBuilder.

Uwzględnienie minimalnych funkcji przynosi korzyści dla przycinania oraz AOT. Aby uzyskać więcej informacji, zobacz Przycinanie samodzielnych wdrożeń i plików wykonywalnych.

Aby uzyskać bardziej szczegółowe informacje, zobacz Porównanie WebApplication.CreateBuilder z CreateSlimBuilder

Generatory źródeł

Ponieważ nieużywany kod jest usuwany podczas publikowania w kontekście natywnego AOT, aplikacja nie może używać nieograniczonego odbicia w czasie wykonywania. Generatory źródeł są używane do tworzenia kodu, który pozwala uniknąć konieczności odbicia. W niektórych przypadkach generatory źródłowe generują kod zoptymalizowany pod kątem AOT nawet wtedy, gdy generator nie jest wymagany.

Aby wyświetlić wygenerowany kod źródłowy, dodaj właściwość EmitCompilerGeneratedFiles do pliku .csproj aplikacji, jak pokazano w poniższym przykładzie.

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

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

</Project>

Uruchom polecenie , dotnet build aby wyświetlić wygenerowany kod. Dane wyjściowe zawierają obj/Debug/net8.0/generated/ katalog zawierający wszystkie wygenerowane pliki dla projektu.

Polecenie dotnet publish kompiluje również pliki źródłowe i generuje skompilowane pliki. Ponadto dotnet publish przekazuje wygenerowane zestawy do natywnego kompilatora IL. Kompilator IL tworzy natywny plik wykonywalny. Natywny plik wykonywalny zawiera natywny kod maszyny.

Biblioteki i natywna usługa AOT

Wiele popularnych bibliotek używanych w projektach ASP.NET Core ma obecnie pewne problemy ze zgodnością w przypadku użycia w projekcie przeznaczonym dla natywnej funkcji AOT, takich jak:

  • Używanie odbicia do sprawdzania i odnajdywania typów.
  • Warunkowe ładowanie bibliotek w czasie wykonywania.
  • Generowanie kodu na bieżąco w celu zaimplementowania funkcji.

Biblioteki korzystające z tych funkcji dynamicznych należy zaktualizować w celu pracy z natywną usługą AOT. Można je aktualizować przy użyciu narzędzi, takich jak generatory źródeł Roslyn.

Autorzy bibliotek, którzy mają nadzieję obsługiwać natywne AOT, są zachęcani do:

Minimalne interfejsy API i ładunki JSON

Minimalna struktura interfejsu API jest zoptymalizowana pod kątem odbierania i zwracania ładunków JSON przy użyciu polecenia System.Text.Json. System.Text.Json:

  • Nakłada wymagania dotyczące zgodności dla formatu JSON i natywnego AOT.
  • Wymaga użycia generatora źródeł System.Text.Json.

Wszystkie typy przesyłane jako część treści HTTP lub zwracane z delegatów żądań w aplikacjach minimalnych interfejsów API muszą być skonfigurowane na obiekcie JsonSerializerContext , który jest zarejestrowany za pośrednictwem wstrzykiwania zależności 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
{
}

W poprzednim wyróżnionym kodzie:

Parametr delegata, który nie jest powiązany z treścią i nie musi być serializowalny. Na przykład parametr ciągu zapytania, który jest bogatym typem obiektu i implementuje element 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.

Znane problemy

Zobacz to zadanie GitHub, aby zgłosić lub przejrzeć problemy z natywną obsługą Native AOT w ASP.NET Core.

Zobacz też