Skip to content

Add Microsoft.AspNetCore.OpenApi to the webapiaot template (with an optional flag to disable it) #60337

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 22 commits into from
Mar 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
3b9c7a6
Add basic set up for the new flag with translations by Copilot
sander1095 Feb 12, 2025
734817a
Add conditional logic to use OpenAPI
sander1095 Feb 12, 2025
5be274c
Add OpenAPI test to WebAPIAOT template tests
sander1095 Feb 12, 2025
d8693b2
Fix tests
sander1095 Feb 12, 2025
d0b3ce9
Add missing endif in the csproj
sander1095 Feb 12, 2025
ffee0b2
Add more metadata to get 404 not found in the openapi doc correctly
sander1095 Feb 12, 2025
94e40fd
Also add the 404 metadata to the other file
sander1095 Feb 12, 2025
d918e32
Change elif to else
sander1095 Feb 14, 2025
664bec6
Remove unnecessary 118n changes
sander1095 Feb 14, 2025
e225cc2
Add english translation back
sander1095 Feb 14, 2025
539ba41
Keep the semicolon on the same line as requested by PR review
sander1095 Feb 14, 2025
06112f2
Use TypedResults instead of extension methods and reduce the if else …
sander1095 Feb 14, 2025
8dc2ceb
Add template strings back after running `bash build.sh -test -configu…
sander1095 Feb 14, 2025
98332af
Merge branch 'main' into GH-59564-webapiaot-openapi
sander1095 Mar 3, 2025
a442d80
Add usings for TypedResults and Results/NotFound/Ok etc..
sander1095 Mar 3, 2025
0891a99
Add OpenAPI services to Program.Main.cs
sander1095 Mar 3, 2025
3c4d854
Remove http using because thats already part of the implicit usings
sander1095 Mar 3, 2025
63cf302
TEMP COMMIT - Removing EnableOpenAPI flags to find out why tests fail
sander1095 Mar 4, 2025
9674e32
Revert "TEMP COMMIT - Removing EnableOpenAPI flags to find out why te…
sander1095 Mar 4, 2025
983ec24
Fix assertions where we expected OpenAPI to be enabled for published …
sander1095 Mar 4, 2025
102bbb4
Added consistent indentation in test methods
sander1095 Mar 4, 2025
7cf3a0b
Fix build errors
sander1095 Mar 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,10 @@
<PublishAot>true</PublishAot>
</PropertyGroup>

<!--#if (EnableOpenAPI) -->
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="${MicrosoftAspNetCoreOpenApiVersion}" Condition="'$(EnableOpenAPI)' == 'True'" />
</ItemGroup>
<!--#endif -->

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,13 @@
"UseProgramMain": {
"longName": "use-program-main",
"shortName": ""
},
"DisableOpenAPI": {
"longName": "no-openapi",
"shortName": ""
}
},
"usageExamples": [
""
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,21 @@
"isVisible": true,
"persistenceScope": "shared",
"persistenceScopeName": "Microsoft"
},
{
"id": "DisableOpenAPI",
"name": {
"text": "Enable _OpenAPI support",
"overrideDefaultText": true
},
"description": {
"text": "Enables OpenAPI (Swagger) support",
"overrideDefaultText": true
},
"invertBoolean": true,
"isVisible": true,
"defaultValue": "true",
"persistenceScope": "templateGroup"
}
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"symbols/skipRestore/description": "Pokud se tato možnost zadá, přeskočí automatické obnovení projektu při vytvoření.",
"symbols/UseProgramMain/displayName": "Nepoužívat _příkazy nejvyšší úrovně",
"symbols/UseProgramMain/description": "Určuje, jestli se má místo příkazů nejvyšší úrovně generovat explicitní třída Program a metoda Main.",
"symbols/DisableOpenAPI/description": "Disable OpenAPI (Swagger) support",
"postActions/restore/description": "Obnoví balíčky NuGet vyžadované tímto projektem.",
"postActions/restore/manualInstructions/default/text": "Spustit dotnet restore"
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"symbols/skipRestore/description": "Wenn angegeben, wird die automatische Wiederherstellung des Projekts beim Erstellen übersprungen.",
"symbols/UseProgramMain/displayName": "Keine Anweisungen_der obersten Ebene verwenden",
"symbols/UseProgramMain/description": "Gibt an, ob anstelle von Anweisungen der obersten Ebene eine explizite Programmklasse und eine Main-Methode generiert werden soll.",
"symbols/DisableOpenAPI/description": "Disable OpenAPI (Swagger) support",
"postActions/restore/description": "„NuGet-Pakete“ wiederherstellen, die für dieses Projekt erforderlich sind.",
"postActions/restore/manualInstructions/default/text": "„dotnet restore“ ausführen"
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"author": "Microsoft",
"name": "ASP.NET Core Web API (native AOT)",
"description": "A project template for creating a RESTful Web API using ASP.NET Core minimal APIs published as native AOT.",
"description": "A project template for creating a RESTful Web API using ASP.NET Core minimal APIs published as native AOT, with optional support for OpenAPI.",
"symbols/ExcludeLaunchSettings/description": "Whether to exclude launchSettings.json from the generated template.",
"symbols/kestrelHttpPort/description": "Port number to use for the HTTP endpoint in launchSettings.json.",
"symbols/iisHttpPort/description": "Port number to use for the IIS Express HTTP endpoint in launchSettings.json.",
Expand All @@ -10,6 +10,7 @@
"symbols/skipRestore/description": "If specified, skips the automatic restore of the project on create.",
"symbols/UseProgramMain/displayName": "Do not use _top-level statements",
"symbols/UseProgramMain/description": "Whether to generate an explicit Program class and Main method instead of top-level statements.",
"symbols/DisableOpenAPI/description": "Disable OpenAPI (Swagger) support",
"postActions/restore/description": "Restore NuGet packages required by this project.",
"postActions/restore/manualInstructions/default/text": "Run 'dotnet restore'"
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"symbols/skipRestore/description": "Si se especifica, se omite la restauración automática del proyecto durante la creación.",
"symbols/UseProgramMain/displayName": "No usar instrucciones de _nivel superior",
"symbols/UseProgramMain/description": "Indica si se debe generar una clase Program explícita y un método Main en lugar de instrucciones de nivel superior.",
"symbols/DisableOpenAPI/description": "Disable OpenAPI (Swagger) support",
"postActions/restore/description": "Restaure los paquetes NuGet necesarios para este proyecto.",
"postActions/restore/manualInstructions/default/text": "Ejecutar \"dotnet restore\""
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"symbols/skipRestore/description": "S’il est spécifié, ignore la restauration automatique du projet lors de la création.",
"symbols/UseProgramMain/displayName": "N’utilisez pas _d’instructions de niveau supérieur.",
"symbols/UseProgramMain/description": "Indique s’il faut générer une classe Programme explicite et une méthode Main au lieu d’instructions de niveau supérieur.",
"symbols/DisableOpenAPI/description": "Disable OpenAPI (Swagger) support",
"postActions/restore/description": "Restaurez les packages NuGet requis par ce projet.",
"postActions/restore/manualInstructions/default/text": "Exécuter « dotnet restore »"
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"symbols/skipRestore/description": "Se specificato, ignora il ripristino automatico del progetto durante la creazione.",
"symbols/UseProgramMain/displayName": "Non usare_istruzioni di primo livello",
"symbols/UseProgramMain/description": "Indica se generare una classe Program esplicita e un metodo Main anziché istruzioni di primo livello.",
"symbols/DisableOpenAPI/description": "Disable OpenAPI (Swagger) support",
"postActions/restore/description": "Ripristina i pacchetti NuGet richiesti da questo progetto.",
"postActions/restore/manualInstructions/default/text": "Esegui 'dotnet restore'"
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"symbols/skipRestore/description": "指定した場合、作成時にプロジェクトの自動復元がスキップされます。",
"symbols/UseProgramMain/displayName": "最上位レベルのステートメントを使用しない(_T)",
"symbols/UseProgramMain/description": "最上位レベルのステートメントではなく、明示的な Program クラスと Main メソッドを生成するかどうか。",
"symbols/DisableOpenAPI/description": "Disable OpenAPI (Swagger) support",
"postActions/restore/description": "このプロジェクトに必要な NuGet パッケージを復元します。",
"postActions/restore/manualInstructions/default/text": "'dotnet restore' を実行する"
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"symbols/skipRestore/description": "지정된 경우, 프로젝트 생성 시 자동 복원을 건너뜁니다.",
"symbols/UseProgramMain/displayName": "최상위 문 사용 안 함(_T)",
"symbols/UseProgramMain/description": "최상위 문 대신 명시적 Program 클래스 및 Main 메서드를 생성할지 여부입니다.",
"symbols/DisableOpenAPI/description": "Disable OpenAPI (Swagger) support",
"postActions/restore/description": "이 프로젝트에 필요한 NuGet 패키지를 복원합니다.",
"postActions/restore/manualInstructions/default/text": "'dotnet restore' 실행"
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"symbols/skipRestore/description": "Jeśli ta opcja jest określona, pomija automatyczne przywracanie projektu podczas tworzenia.",
"symbols/UseProgramMain/displayName": "Nie używaj ins_trukcji najwyższego poziomu",
"symbols/UseProgramMain/description": "Określa, czy wygenerować jawną klasę Program i metodę Main zamiast instrukcji najwyższego poziomu.",
"symbols/DisableOpenAPI/description": "Disable OpenAPI (Swagger) support",
"postActions/restore/description": "Przywróć pakiety NuGet wymagane przez ten projekt.",
"postActions/restore/manualInstructions/default/text": "Uruchom polecenie \"dotnet restore\""
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"symbols/skipRestore/description": "Se especificado, ignora a restauração automática do projeto sendo criado.",
"symbols/UseProgramMain/displayName": "Não use ins_truções de nível superior",
"symbols/UseProgramMain/description": "Se deve gerar uma classe de Programa explícita e um método principal em vez de instruções de nível superior.",
"symbols/DisableOpenAPI/description": "Disable OpenAPI (Swagger) support",
"postActions/restore/description": "Restaure os pacotes NuGet exigidos por este projeto.",
"postActions/restore/manualInstructions/default/text": "Executa 'dotnet restore'"
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"symbols/skipRestore/description": "Если установлено, автоматическое восстановление проекта при создании пропускается.",
"symbols/UseProgramMain/displayName": "Не использовать _операторы верхнего уровня",
"symbols/UseProgramMain/description": "Следует ли создавать явный класс Program и метод Main вместо операторов верхнего уровня.",
"symbols/DisableOpenAPI/description": "Disable OpenAPI (Swagger) support",
"postActions/restore/description": "Восстановление пакетов NuGet, необходимых для этого проекта.",
"postActions/restore/manualInstructions/default/text": "Выполнить команду \"dotnet restore\""
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"symbols/skipRestore/description": "Belirtilirse, oluşturma sırasında projenin otomatik geri yüklenmesini atlar.",
"symbols/UseProgramMain/displayName": "_Üst düzey deyimler kullanmayın",
"symbols/UseProgramMain/description": "Üst düzey deyimler yerine açık bir Program sınıfı ve Ana yöntem oluşturup oluşturulmayacağını belirtir.",
"symbols/DisableOpenAPI/description": "Disable OpenAPI (Swagger) support",
"postActions/restore/description": "Bu projenin gerektirdiği NuGet paketlerini geri yükleyin.",
"postActions/restore/manualInstructions/default/text": "'dotnet restore' çalıştır"
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"symbols/skipRestore/description": "如果指定,则在创建时跳过项目的自动还原。",
"symbols/UseProgramMain/displayName": "不使用顶级语句(_T)",
"symbols/UseProgramMain/description": "是否生成显式程序类和主方法,而不是顶级语句。",
"symbols/DisableOpenAPI/description": "Disable OpenAPI (Swagger) support",
"postActions/restore/description": "还原此项目所需的 NuGet 包。",
"postActions/restore/manualInstructions/default/text": "运行 \"dotnet restore\""
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"symbols/skipRestore/description": "若指定,會在建立時跳過專案的自動還原。",
"symbols/UseProgramMain/displayName": "不要使用最上層陳述式(_T)",
"symbols/UseProgramMain/description": "是否要產生明確的 Program 類別和 Main 方法,而非最上層語句。",
"symbols/DisableOpenAPI/description": "Disable OpenAPI (Swagger) support",
"postActions/restore/description": "還原此專案所需的 NuGet 套件。",
"postActions/restore/manualInstructions/default/text": "執行 'dotnet restore'"
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
],
"name": "ASP.NET Core Web API (native AOT)",
"generatorVersions": "[1.0.0.0-*)",
"description": "A project template for creating a RESTful Web API using ASP.NET Core minimal APIs published as native AOT.",
"description": "A project template for creating a RESTful Web API using ASP.NET Core minimal APIs published as native AOT, with optional support for OpenAPI.",
"groupIdentity": "Microsoft.Web.WebApiAot",
"precedence": "10000",
"identity": "Microsoft.Web.WebApiAot.CSharp.10.0",
Expand Down Expand Up @@ -130,6 +130,16 @@
"defaultValue": "false",
"displayName": "Do not use _top-level statements",
"description": "Whether to generate an explicit Program class and Main method instead of top-level statements."
},
"DisableOpenAPI": {
"type": "parameter",
"dataType": "bool",
"defaultValue": "false",
"description": "Disable OpenAPI (Swagger) support"
},
"EnableOpenAPI": {
"type": "computed",
"value": "(!DisableOpenAPI)"
}
},
"primaryOutputs": [
Expand All @@ -152,4 +162,4 @@
"continueOnError": true
}
]
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Http.HttpResults;

namespace Company.WebApplication1;

Expand All @@ -13,8 +14,20 @@ public static void Main(string[] args)
options.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonSerializerContext.Default);
});

#if (EnableOpenAPI)
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi();
#endif

var app = builder.Build();

#if (EnableOpenAPI)
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
}
#endif

var sampleTodos = new Todo[] {
new(1, "Walk the dog"),
new(2, "Do the dishes", DateOnly.FromDateTime(DateTime.Now)),
Expand All @@ -24,11 +37,23 @@ public static void Main(string[] args)
};

var todosApi = app.MapGroup("/todos");
#if (EnableOpenAPI)
todosApi.MapGet("/", () => sampleTodos)
.WithName("GetTodos");

todosApi.MapGet("/{id}", Results<Ok<Todo>, NotFound> (int id) =>
sampleTodos.FirstOrDefault(a => a.Id == id) is { } todo
? TypedResults.Ok(todo)
: TypedResults.NotFound())
.WithName("GetTodoById");
#else
todosApi.MapGet("/", () => sampleTodos);
todosApi.MapGet("/{id}", (int id) =>

todosApi.MapGet("/{id}", Results<Ok<Todo>, NotFound> (int id) =>
sampleTodos.FirstOrDefault(a => a.Id == id) is { } todo
? Results.Ok(todo)
: Results.NotFound());
? TypedResults.Ok(todo)
: TypedResults.NotFound());
#endif

app.Run();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Http.HttpResults;

var builder = WebApplication.CreateSlimBuilder(args);

Expand All @@ -7,8 +8,20 @@
options.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonSerializerContext.Default);
});

#if (EnableOpenAPI)
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi();
#endif

var app = builder.Build();

#if (EnableOpenAPI)
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
}
#endif

var sampleTodos = new Todo[] {
new(1, "Walk the dog"),
new(2, "Do the dishes", DateOnly.FromDateTime(DateTime.Now)),
Expand All @@ -18,11 +31,23 @@
};

var todosApi = app.MapGroup("/todos");
#if (EnableOpenAPI)
todosApi.MapGet("/", () => sampleTodos)
.WithName("GetTodos");

todosApi.MapGet("/{id}", Results<Ok<Todo>, NotFound> (int id) =>
sampleTodos.FirstOrDefault(a => a.Id == id) is { } todo
? TypedResults.Ok(todo)
: TypedResults.NotFound())
.WithName("GetTodoById");
#else
todosApi.MapGet("/", () => sampleTodos);
todosApi.MapGet("/{id}", (int id) =>

todosApi.MapGet("/{id}", Results<Ok<Todo>, NotFound> (int id) =>
sampleTodos.FirstOrDefault(a => a.Id == id) is { } todo
? Results.Ok(todo)
: Results.NotFound());
? TypedResults.Ok(todo)
: TypedResults.NotFound());
#endif

app.Run();

Expand Down
Loading
Loading