Skip to content

Commit 8f5f1dc

Browse files
committed
Fix incorrect OpenAPI definition when using FromForm with IEnumerable
Fix Issue #62328 - Incorrect OpenAPI definition when using FromForm with IEnumerable parameters
1 parent 9e3f03d commit 8f5f1dc

File tree

2 files changed

+34
-1
lines changed

2 files changed

+34
-1
lines changed

src/OpenApi/src/Services/OpenApiDocumentService.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System.Collections;
45
using System.Collections.Concurrent;
56
using System.Collections.Frozen;
67
using System.ComponentModel;
@@ -665,7 +666,11 @@ private async Task<OpenApiRequestBody> GetFormRequestBody(
665666
}
666667
else
667668
{
668-
if (isComplexType)
669+
// Identify if this is a collection (excluding string)
670+
var isCollection = typeof(IEnumerable).IsAssignableFrom(description.Type) && description.Type != typeof(string);
671+
672+
// Only allow non-collection complex types (POCOs) to take over the root body
673+
if (isComplexType && !isCollection)
669674
{
670675
complexTypeSchema = parameterSchema;
671676
}

src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Services/OpenApiDocumentService/OpenApiDocumentServiceTests.RequestBody.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,6 +1076,34 @@ await VerifyOpenApiDocument(action, document =>
10761076
});
10771077
}
10781078

1079+
[Fact]
1080+
public async Task GetOpenApiRequestBody_HandlesFromFormWithIEnumerable()
1081+
{
1082+
// Arrange
1083+
var builder = CreateBuilder();
1084+
1085+
// Act
1086+
builder.MapPost("/test", ([FromForm] IEnumerable<int> values) => { });
1087+
1088+
// Assert
1089+
await VerifyOpenApiDocument(builder, document =>
1090+
{
1091+
var paths = Assert.Single(document.Paths.Values);
1092+
var operation = paths.Operations[HttpMethod.Post];
1093+
Assert.NotNull(operation.RequestBody);
1094+
var content = operation.RequestBody.Content;
1095+
Assert.Contains("multipart/form-data", content.Keys);
1096+
var formSchema = content["multipart/form-data"].Schema;
1097+
1098+
Assert.Equal(JsonSchemaType.Object, formSchema.Type);
1099+
Assert.NotNull(formSchema.Properties);
1100+
Assert.Contains("values", formSchema.Properties);
1101+
var valuesProperty = formSchema.Properties["values"];
1102+
Assert.Equal(JsonSchemaType.Array, valuesProperty.Type);
1103+
Assert.Equal(JsonSchemaType.Integer, valuesProperty.Items.Type);
1104+
});
1105+
}
1106+
10791107
[Route("/form-mixed-types")]
10801108
private void ActionWithMixedFormTypes([FromForm] Todo todo, IFormFile formFile, [FromForm] Guid guid) { }
10811109

0 commit comments

Comments
 (0)