@@ -34,7 +34,7 @@ await VerifyOpenApiDocument(builder, document =>
3434 var paths = Assert . Single ( document . Paths . Values ) ;
3535 var operation = paths . Operations [ OperationType . Post ] ;
3636 Assert . NotNull ( operation . RequestBody ) ;
37- Assert . False ( operation . RequestBody . Required ) ;
37+ Assert . True ( operation . RequestBody . Required ) ;
3838 Assert . NotNull ( operation . RequestBody . Content ) ;
3939 var content = Assert . Single ( operation . RequestBody . Content ) ;
4040 Assert . Equal ( "multipart/form-data" , content . Key ) ;
@@ -72,7 +72,16 @@ await VerifyOpenApiDocument(builder, document =>
7272 var paths = Assert . Single ( document . Paths . Values ) ;
7373 var operation = paths . Operations [ OperationType . Post ] ;
7474 Assert . NotNull ( operation . RequestBody ) ;
75- Assert . Equal ( ! isOptional , operation . RequestBody . Required ) ;
75+ Assert . True ( operation . RequestBody . Required ) ;
76+ var schema = operation . RequestBody . Content [ "multipart/form-data" ] . Schema ;
77+ if ( ! isOptional )
78+ {
79+ Assert . Contains ( "formFile" , schema . Required ) ;
80+ }
81+ else
82+ {
83+ Assert . DoesNotContain ( "formFile" , schema . Required ) ;
84+ }
7685 } ) ;
7786 }
7887#nullable restore
@@ -101,7 +110,7 @@ await VerifyOpenApiDocument(builder, document =>
101110 var paths = Assert . Single ( document . Paths . Values ) ;
102111 var operation = paths . Operations [ OperationType . Post ] ;
103112 Assert . NotNull ( operation . RequestBody ) ;
104- Assert . False ( operation . RequestBody . Required ) ;
113+ Assert . True ( operation . RequestBody . Required ) ;
105114 Assert . NotNull ( operation . RequestBody . Content ) ;
106115 var content = Assert . Single ( operation . RequestBody . Content ) ;
107116 Assert . Equal ( "multipart/form-data" , content . Key ) ;
@@ -140,7 +149,16 @@ await VerifyOpenApiDocument(builder, document =>
140149 var paths = Assert . Single ( document . Paths . Values ) ;
141150 var operation = paths . Operations [ OperationType . Post ] ;
142151 Assert . NotNull ( operation . RequestBody ) ;
143- Assert . Equal ( ! isOptional , operation . RequestBody . Required ) ;
152+ Assert . True ( operation . RequestBody . Required ) ;
153+ var schema = operation . RequestBody . Content [ "multipart/form-data" ] . Schema ;
154+ if ( ! isOptional )
155+ {
156+ Assert . Contains ( "formFile" , schema . Required ) ;
157+ }
158+ else
159+ {
160+ Assert . DoesNotContain ( "formFile" , schema . Required ) ;
161+ }
144162 } ) ;
145163 }
146164#nullable restore
@@ -401,6 +419,10 @@ await VerifyOpenApiDocument(builder, document =>
401419 Assert . NotNull ( item . Schema ) ;
402420 Assert . Equal ( "object" , item . Schema . Type ) ;
403421 Assert . NotNull ( item . Schema . Properties ) ;
422+ Assert . Contains ( "id" , item . Schema . Required ) ;
423+ Assert . Contains ( "title" , item . Schema . Required ) ;
424+ Assert . Contains ( "completed" , item . Schema . Required ) ;
425+ Assert . Contains ( "createdAt" , item . Schema . Required ) ;
404426 Assert . Collection ( item . Schema . Properties ,
405427 property =>
406428 {
@@ -427,6 +449,57 @@ await VerifyOpenApiDocument(builder, document =>
427449 } ) ;
428450 }
429451
452+ // Test coverage for https://github.com/dotnet/aspnetcore/issues/57112
453+ [ Fact ]
454+ public async Task GetOpenApiRequestBody_HandlesFromFormWithRequiredPrimitive ( )
455+ {
456+ // Arrange
457+ var builder = CreateBuilder ( ) ;
458+
459+ // Act
460+ builder . MapPost ( "/form" , ( [ FromForm ] int id , [ FromForm ] DateTime date , [ FromForm ] short ? value ) => { } ) ;
461+
462+ // Assert
463+ await VerifyOpenApiDocument ( builder , document =>
464+ {
465+ var paths = Assert . Single ( document . Paths . Values ) ;
466+ var operation = paths . Operations [ OperationType . Post ] ;
467+ Assert . NotNull ( operation . RequestBody ) ;
468+ Assert . NotNull ( operation . RequestBody . Content ) ;
469+ var content = operation . RequestBody . Content ;
470+ // Forms can be provided in both the URL and via form data
471+ Assert . Contains ( "application/x-www-form-urlencoded" , content . Keys ) ;
472+ // Same schema should be produced for both content-types
473+ foreach ( var item in content . Values )
474+ {
475+ Assert . NotNull ( item . Schema ) ;
476+ Assert . Equal ( "object" , item . Schema . Type ) ;
477+ Assert . NotNull ( item . Schema . Properties ) ;
478+ // Assert that requiredness has been set for primitives
479+ Assert . Contains ( "id" , item . Schema . Required ) ;
480+ Assert . Contains ( "date" , item . Schema . Required ) ;
481+ Assert . DoesNotContain ( "value" , item . Schema . Required ) ;
482+ Assert . Collection ( item . Schema . AllOf ,
483+ subSchema =>
484+ {
485+ Assert . Contains ( "id" , subSchema . Properties ) ;
486+ Assert . Equal ( "integer" , subSchema . Properties [ "id" ] . Type ) ;
487+ } ,
488+ subSchema =>
489+ {
490+ Assert . Contains ( "date" , subSchema . Properties ) ;
491+ Assert . Equal ( "string" , subSchema . Properties [ "date" ] . Type ) ;
492+ Assert . Equal ( "date-time" , subSchema . Properties [ "date" ] . Format ) ;
493+ } ,
494+ subSchema =>
495+ {
496+ Assert . Contains ( "value" , subSchema . Properties ) ;
497+ Assert . Equal ( "integer" , subSchema . Properties [ "value" ] . Type ) ;
498+ } ) ;
499+ }
500+ } ) ;
501+ }
502+
430503 [ Fact ]
431504 public async Task GetOpenApiRequestBody_HandlesFromFormWithPoco_MvcAction ( )
432505 {
0 commit comments