Repository navigation
Support multiple response types per status code - #4100
martincostello merged 2 commits into
Conversation
Group SupportedResponseTypes by status code in SwaggerGenerator and merge the schemas for each content type into an `anyOf` when more than one distinct type is reported. Previously a second response type for the same status code caused OpenApiResponses.Add to throw an ArgumentException (domaindrivendev#2413, domaindrivendev#2743). This pre-fixes Swashbuckle for .NET 11 C# unions, where the framework can surface multiple response types (or union cases) for a single status code. The single-response path is unchanged, so existing documents are byte for byte identical. Adds unit tests plus a MultipleResponseTypes integration fixture that injects a second response type via a custom IApiDescriptionProvider (the API explorer collapses duplicates on net8-10), with snapshots verifying the generated document and that Kiota and NSwag generate and compile valid clients from the anyOf schema. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 7722de8a-3ea5-40fd-999a-4f647ce8f4f7
There was a problem hiding this comment.
Pull request overview
Adds first-class handling for multiple distinct response types per HTTP status code in SwaggerGenerator, emitting a single response entry whose per-content-type schema becomes an anyOf when needed. This prevents OpenApiResponses.Add collisions when ASP.NET Core surfaces multiple ApiResponseType entries for the same status code (notably aligned with upcoming .NET 11 behavior).
Changes:
- Group
SupportedResponseTypesby status code and merge schemas per content type into a single response usinganyOfwhen multiple distinct types are present. - Add unit coverage for merging, deduplication, and ignoring typeless (
void) responses during merge. - Add an end-to-end integration fixture (
MultipleResponseTypes) plus updated snapshots verifying output and client-generation compatibility (Kiota + NSwag).
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| test/WebSites/MultipleResponseTypes/Program.cs | Minimal app + custom IApiDescriptionProvider to inject a second response type for the same status code. |
| test/WebSites/MultipleResponseTypes/MultipleResponseTypes.csproj | New website project for integration testing the multi-response behavior. |
| test/Swashbuckle.AspNetCore.SwaggerGen.Test/SwaggerGenerator/SwaggerGeneratorTests.cs | Unit tests validating anyOf merge behavior, schema dedupe, and void-response handling. |
| test/Swashbuckle.AspNetCore.IntegrationTests/VerifyTests.cs | Adds the new website to JSON validity snapshot verification. |
| test/Swashbuckle.AspNetCore.IntegrationTests/SwaggerIntegrationTests.cs | Adds the new website to middleware integration coverage. |
| test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_9af902faded38cfc/Models/Dog.verified.cs | Kiota-generated model snapshot for the new response type. |
| test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_9af902faded38cfc/Models/Cat.verified.cs | Kiota-generated model snapshot for the existing response type. |
| test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_9af902faded38cfc/KiotaOpenApiClient.verified.cs | Kiota client snapshot validating composed response generation. |
| test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_9af902faded38cfc/Animals/Item/AnimalsItemRequestBuilder.verified.cs | Kiota request builder snapshot showing composed (anyOf) response wrapper usage. |
| test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_9af902faded38cfc/Animals/AnimalsRequestBuilder.verified.cs | Kiota request builder snapshot for the new endpoint path. |
| test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_653e9faaca680294/NSwagOpenApiClient.verified.cs | NSwag client snapshot validating code generation/compilation against anyOf. |
| test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/8_0/VerifyTests.Swagger_IsValidJson_No_Startup_entryPointType=MultipleResponseTypes.Program_swaggerRequestUri=v1.verified.txt | OpenAPI JSON snapshot (net8) showing anyOf for 200 response schema. |
| test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/9_0/VerifyTests.Swagger_IsValidJson_No_Startup_entryPointType=MultipleResponseTypes.Program_swaggerRequestUri=v1.verified.txt | OpenAPI JSON snapshot (net9) showing anyOf for 200 response schema. |
| test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/10_0/VerifyTests.Swagger_IsValidJson_No_Startup_entryPointType=MultipleResponseTypes.Program_swaggerRequestUri=v1.verified.txt | OpenAPI JSON snapshot (net10) showing anyOf for 200 response schema. |
| src/Swashbuckle.AspNetCore.SwaggerGen/SwaggerGenerator/SwaggerGenerator.cs | Core implementation: group responses by status code and merge schemas per content type into anyOf when needed. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #4100 +/- ##
==========================================
+ Coverage 95.19% 95.21% +0.01%
==========================================
Files 111 111
Lines 4101 4115 +14
Branches 838 843 +5
==========================================
+ Hits 3904 3918 +14
Misses 197 197
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
This is great, thanks @DeagleGross! |
…nto union schema support Branch 1 (multiple response types per status code) was squash-merged upstream as commit 00d5017. This branch still carried the original branch-1 commit (c9d12cf) plus the union schema work, so merging produced comment-only conflicts in SwaggerGenerator.cs. Resolved by taking upstream/master's comment wording (the code was identical). All union changes preserved: SchemaGenerator TryGenerateUnionSchema, JsonSerializerDataContractResolver TryGetUnionCaseTypes, the union tests, net11 TFM additions, and the global.json net11 preview pin. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 7722de8a-3ea5-40fd-999a-4f647ce8f4f7
|
Thanks for your contribution @DeagleGross - the changes from this pull request have been published as part of version 10.3.0 📦, which is now available from NuGet.org 🚀 |
Group SupportedResponseTypes by status code in SwaggerGenerator and merge the schemas for each content type into an
anyOfwhen more than one distinct type is reported. Previously a second response type for the same status code caused OpenApiResponses.Add to throw an ArgumentException (#2413, #2743).This PR aligns with net11 aspnetcore changes - see dotnet/aspnetcore#55412 and dotnet/aspnetcore#56177 where the framework can surface multiple response types for a single status code. Moreover, this is a prerequisite for .NET11 C# unions. The single-response path is unchanged, so existing documents are byte for byte identical.
Adds unit tests plus a MultipleResponseTypes integration fixture that injects a second response type via a custom IApiDescriptionProvider (the API explorer collapses duplicates on net8-10), with snapshots verifying the generated document and that Kiota and NSwag generate and compile valid clients from the anyOf schema.
Fixes #2413
Fixes #2743