Start Debugging

WebApplication.CreateBuilder vs CreateSlimBuilder vs CreateEmptyBuilder in ASP.NET Core 11

Verwenden Sie CreateBuilder für eine normale App, CreateSlimBuilder, wenn Sie getrimmt oder mit Native AOT hinter einem TLS-Proxy veröffentlichen, und CreateEmptyBuilder nur, wenn Sie jeden Dienst selbst registrieren möchten. Hier ist die Feature-Matrix samt der Stolperfallen, die die Entscheidung erzwingen.

Für eine normale ASP.NET Core 11 Web-App verwenden Sie WebApplication.CreateBuilder(args). Es ist nicht ohne Grund die Standardwahl: Es verdrahtet jede Hosting-Funktion, die Sie erwarten. Wechseln Sie nur dann zu WebApplication.CreateSlimBuilder(args), wenn Sie mit Trimming oder Native AOT veröffentlichen und hinter einem TLS-terminierenden Proxy laufen, denn es entfernt HTTPS, HTTP/3, die IIS-Integration, statische Web-Assets und zwei Logging-Provider, um die Binärdatei zu verkleinern. Greifen Sie nur in dem seltenen Fall zu WebApplication.CreateEmptyBuilder(...), in dem Sie eine nahezu leere Grundlage möchten und den Server, das Routing und die Konfiguration selbst registrieren. Dieser Beitrag zielt auf .NET 11 (zum Zeitpunkt des Schreibens Preview 6, GA im November 2026) mit Microsoft.NET.Sdk.Web und C# 14, aber alle drei Factory-Methoden existieren seit .NET 8, sodass die Empfehlung auf .NET 8 bis 11 unverändert gilt.

Was “Standards” hier tatsächlich bedeutet

Die drei Methoden unterscheiden sich in genau einer Sache: wie viel sie in den WebApplicationBuilder registrieren, bevor Ihr Code läuft. Alles andere, die builder.Services Sammlung, builder.Build(), app.MapGet(...), ist identisch. Die gesamte Entscheidung läuft also darauf hinaus, welche Standards Sie geliefert bekommen möchten und welche Sie bereit sind, von Hand nachzurüsten.

CreateBuilder gibt Ihnen den vollständigen Standard-Host. CreateSlimBuilder gibt Ihnen eine kuratierte Teilmenge, die auf Trim-Sicherheit und geringe Größe ausgelegt ist. CreateEmptyBuilder gibt Ihnen fast nichts und erwartet, dass Sie sich für jeden Baustein einzeln entscheiden. Intern teilen sie sich sogar die Maschinerie: CreateSlimBuilder baut auf demselben leeren Host-Application-Builder auf, den CreateEmptyBuilder bereitstellt, und fügt dann die schlanke Menge an Diensten darüber wieder hinzu. Deshalb ist die untenstehende Reihenfolge eine strikte Obermengenkette: CreateBuilder enthält alles, was CreateSlimBuilder enthält, was wiederum alles enthält, was CreateEmptyBuilder enthält.

Feature-Matrix

Jede Zeile ist gegen die ASP.NET Core 11 Dokumentation und den WebApplication.cs Quellcode verifiziert. “Manuell” bedeutet, dass die Funktion nicht für Sie registriert wird, Sie sie aber mit dem angegebenen Aufruf hinzufügen können.

FunktionCreateBuilderCreateSlimBuilderCreateEmptyBuilder
appsettings.json + appsettings.{env}.jsonjajamanuell
User Secrets (Development)jajamanuell
Umgebungsvariablen- + Kommandozeilenkonfigurationjajamanuell
Console-Loggingjajamanuell (AddConsole)
Debug / EventSource / EventLog Loggingjaneinnein
Kestrel-ServervollständigKern (UseKestrelCore)manuell (UseKestrelCore)
HTTPS-Endpunkte in Kestreljanein (UseKestrelHttpsConfiguration)manuell
HTTP/3 (QUIC)janein (UseQuic)manuell
IIS-Integrationjaneinnein
Statische Web-Assetsjaneinnein
Hosting-Startup-Assemblies / UseStartupjaneinnein
Regex- und Alpha-Routing-Constraintsjaneinnein
Routing / MapGet usw.jajamanuell

Die wichtigste Erkenntnis aus dieser Tabelle: CreateSlimBuilder behält weiterhin Ihre Konfigurationsquellen und das Console-Logging. Es entfernt nicht die Dinge, die Sie täglich nutzen. Es entfernt Protokoll- und Plattformfunktionen, die eine cloud-native, mit Proxy vorgeschaltete Bereitstellung normalerweise nicht benötigt, sowie drei Logging-Provider, die Sie in der Produktion selten lesen.

Wann Sie CreateBuilder wählen sollten

Dies ist der Standard, und für die meisten Apps sollte es der Standard bleiben.

Wann Sie CreateSlimBuilder wählen sollten

CreateSlimBuilder wurde in .NET 8 speziell eingeführt, um der Standard für das Native AOT Web API Template (dotnet new webapiaot) zu sein. Wählen Sie es, wenn das Folgende Ihre Bereitstellung beschreibt.

Wenn Sie Slim wählen und später feststellen, dass Sie doch HTTPS oder HTTP/3 benötigen, müssen Sie nicht den Builder wechseln. Fügen Sie sie explizit wieder hinzu:

// .NET 11, C# 14
var builder = WebApplication.CreateSlimBuilder(args);

// Re-enable HTTPS endpoints that CreateSlimBuilder omits by default.
builder.WebHost.UseKestrelHttpsConfiguration();

// Re-enable HTTP/3 (QUIC) if a client actually needs it.
builder.WebHost.UseQuic();

var app = builder.Build();
app.MapGet("/", () => "Hello from a slim host");
app.Run();

Wann Sie CreateEmptyBuilder wählen sollten

CreateEmptyBuilder(WebApplicationOptions) erstellt einen Builder ganz ohne eingebautes Verhalten. Die App, die er baut, enthält nur die Dienste und Middleware, die Sie explizit konfigurieren. Dies ist ein Spezialwerkzeug, kein allgemeiner Standard. Greifen Sie dazu, wenn Sie den kleinstmöglichen Dienst bauen und jede Registrierung kontrollieren möchten, oder wenn Sie damit experimentieren, wie wenig ASP.NET Core genau benötigt, um eine Anfrage zu bedienen.

Hier ist das kanonische minimale Beispiel aus den .NET 8 Release Notes, das auf .NET 11 immer noch unverändert kompiliert:

// .NET 11, C# 14
var builder = WebApplication.CreateEmptyBuilder(new WebApplicationOptions());

// Nothing is registered by default, so add the server yourself.
builder.WebHost.UseKestrelCore();

var app = builder.Build();

app.Use(async (context, next) =>
{
    await context.Response.WriteAsync("Hello, World!");
    await next(context);
});

Console.WriteLine("Running...");
app.Run();

Beachten Sie, was fehlt und von Hand hinzugefügt werden müsste, wenn Sie es benötigten: Es gibt kein Laden von appsettings.json, kein Console-Logging, kein Routing (also kein MapGet; Sie schreiben stattdessen rohe Middleware) und keine Konfigurationsbindung. Sie fügen jedes mit einem expliziten Aufruf hinzu: builder.Configuration.AddJsonFile("appsettings.json"), builder.Logging.AddConsole(), builder.Services.AddRouting() und so weiter. Genau das ist der Sinn des leeren Builders: Sie zahlen für genau das, was Sie nutzen.

Die Größenfrage, und warum es eine Trimming-Frage ist

Der Grund, warum alle drei existieren, ist Binärgröße und Startzeit für Native AOT, nicht der reine Anfragendurchsatz. Bei einer JIT-kompilierten App registrieren die drei Builder unterschiedliche Dienstgraphen, aber sobald die App warm ist, liegt der Unterschied bei den Anfragen pro Sekunde nicht dort, wo der Wert steckt. Der Wert zeigt sich, wenn Sie trimmen und AOT-kompilieren.

Microsofts eigener Benchmark für das Native AOT Web API Template vergleicht eine Native-AOT-Veröffentlichung mit einem getrimmten Laufzeit-Build und einem ungetrimmten Laufzeit-Build und berichtet, dass die AOT-App von den dreien die geringste App-Größe, den geringsten Speicherverbrauch und die kürzeste Startzeit hat. Die .NET 8 Release Notes liefern einen konkreten Anker für das leere Ende des Spektrums: Das CreateEmptyBuilder “Hello, World”-Beispiel oben, mit Native AOT auf einer linux-x64-Maschine veröffentlicht, erzeugte eine eigenständige native ausführbare Datei von etwa 8,5 MB. Diese Zahl ist es, wie eine nahezu leere Grundlage aussieht, sobald AOT und Trimming ihre Arbeit tun.

Die praktische Reihenfolge, vom größten zum kleinsten veröffentlichten Footprint, ist CreateBuilder, dann CreateSlimBuilder, dann CreateEmptyBuilder. Aber die Lücke zwischen ihnen öffnet sich nur unter PublishAot oder PublishTrimmed. Liefern Sie einen einfachen Build aus, und Sie haben die Zeremonie des Slim- oder leeren Builders bezahlt, ohne die Belohnung einzustreichen. Das ist der mit Abstand häufigste Fehler: den Slim-Builder für eine normale Bereitstellung zu wählen, weil “Slim klingt schneller”. Er ist zur Laufzeit nicht schneller; er ist getrimmt kleiner. Wenn Sie nicht trimmen, lohnt es sich, was Native AOT Sie tatsächlich kostet zu lesen, bevor Sie sich auf den Slim-Pfad festlegen, und Native AOT vs ReadyToRun vs JIT behandelt, wo jeder Veröffentlichungsmodus gewinnt.

Die Stolperfalle, die für Sie entscheidet

Präferenz entscheidet das selten. Eines von diesen tut es meist.

Die Entscheidung, noch einmal formuliert

Wählen Sie standardmäßig CreateBuilder. Es ist die richtige Wahl für die überwältigende Mehrheit der ASP.NET Core 11 Apps, einschließlich jeder App, die IIS, statische Web-Assets, MVC, Blazor oder Regex-Route-Constraints verwendet. Wechseln Sie zu CreateSlimBuilder, wenn und nur wenn Sie getrimmt oder mit Native AOT veröffentlichen und hinter einem TLS-terminierenden Proxy sitzen, was genau das Szenario ist, auf das das webapiaot Template abzielt; fügen Sie HTTPS oder HTTP/3 mit einem einzigen UseKestrelHttpsConfiguration() oder UseQuic() Aufruf wieder hinzu, falls Sie sie benötigen. Behalten Sie CreateEmptyBuilder für den wirklich minimalen Dienst in der Hinterhand, bei dem Sie jedes einzelne Teil selbst registrieren und die Untergrenze messen möchten. Das Einzige, was Sie nicht tun sollten, ist, den Slim- oder leeren Builder für eine normale JIT-Bereitstellung zu wählen, mit der Theorie, dass er schneller sei. Er ist getrimmt kleiner, nicht laufend schneller, und bei einem normalen Build bekommen Sie die Reibung ohne die Gegenleistung. Wenn Sie überhaupt erst einen älteren Host auf dieses Modell migrieren, ist die Migration von IWebHostBuilder zu WebApplication.CreateBuilder die Hürde, die Sie nehmen müssen, bevor Sie optimieren, welche Factory-Methode Sie aufrufen.

Verwandt

Quellen

Comments

Sign in with GitHub to comment. Reactions and replies thread back to the comments repo.

< Zurück