@@ -92,12 +92,14 @@ private ApiDescription CreateApiDescription(RouteEndpoint routeEndpoint, string
92
92
{
93
93
DisplayName = routeEndpoint . DisplayName ,
94
94
RouteValues =
95
- {
96
- [ "controller" ] = controllerName ,
97
- } ,
95
+ {
96
+ [ "controller" ] = controllerName ,
97
+ } ,
98
98
} ,
99
99
} ;
100
100
101
+ var hasBodyOrFormFileParameter = false ;
102
+
101
103
foreach ( var parameter in methodInfo . GetParameters ( ) )
102
104
{
103
105
var parameterDescription = CreateApiParameterDescription ( parameter , routeEndpoint . RoutePattern ) ;
@@ -108,23 +110,33 @@ private ApiDescription CreateApiDescription(RouteEndpoint routeEndpoint, string
108
110
}
109
111
110
112
apiDescription . ParameterDescriptions . Add ( parameterDescription ) ;
113
+
114
+ hasBodyOrFormFileParameter |=
115
+ parameterDescription . Source == BindingSource . Body ||
116
+ parameterDescription . Source == BindingSource . FormFile ;
111
117
}
112
118
113
119
// Get IAcceptsMetadata.
114
120
var acceptsMetadata = routeEndpoint . Metadata . GetMetadata < IAcceptsMetadata > ( ) ;
115
121
if ( acceptsMetadata is not null )
116
122
{
117
- var acceptsRequestType = acceptsMetadata . RequestType ;
118
- var isOptional = acceptsMetadata . IsOptional ;
119
- var parameterDescription = new ApiParameterDescription
123
+ // Add a default body parameter if there was no explicitly defined parameter associated with
124
+ // either the body or a form and the user explicity defined some metadata describing the
125
+ // content types the endpoint consumes (such as Accepts<TRequest>(...) or [Consumes(...)]).
126
+ if ( ! hasBodyOrFormFileParameter )
120
127
{
121
- Name = acceptsRequestType is not null ? acceptsRequestType . Name : typeof ( void ) . Name ,
122
- ModelMetadata = CreateModelMetadata ( acceptsRequestType ?? typeof ( void ) ) ,
123
- Source = BindingSource . Body ,
124
- Type = acceptsRequestType ?? typeof ( void ) ,
125
- IsRequired = ! isOptional ,
126
- } ;
127
- apiDescription . ParameterDescriptions . Add ( parameterDescription ) ;
128
+ var acceptsRequestType = acceptsMetadata . RequestType ;
129
+ var isOptional = acceptsMetadata . IsOptional ;
130
+ var parameterDescription = new ApiParameterDescription
131
+ {
132
+ Name = acceptsRequestType is not null ? acceptsRequestType . Name : typeof ( void ) . Name ,
133
+ ModelMetadata = CreateModelMetadata ( acceptsRequestType ?? typeof ( void ) ) ,
134
+ Source = BindingSource . Body ,
135
+ Type = acceptsRequestType ?? typeof ( void ) ,
136
+ IsRequired = ! isOptional ,
137
+ } ;
138
+ apiDescription . ParameterDescriptions . Add ( parameterDescription ) ;
139
+ }
128
140
129
141
var supportedRequestFormats = apiDescription . SupportedRequestFormats ;
130
142
@@ -148,8 +160,7 @@ private ApiDescription CreateApiDescription(RouteEndpoint routeEndpoint, string
148
160
var ( source , name , allowEmpty , paramType ) = GetBindingSourceAndName ( parameter , pattern ) ;
149
161
150
162
// Services are ignored because they are not request parameters.
151
- // We ignore/skip body parameter because the value will be retrieved from the IAcceptsMetadata.
152
- if ( source == BindingSource . Services || source == BindingSource . Body )
163
+ if ( source == BindingSource . Services )
153
164
{
154
165
return null ;
155
166
}
@@ -239,6 +250,10 @@ private static ParameterDescriptor CreateParameterDescriptor(ParameterInfo param
239
250
{
240
251
return ( BindingSource . Body , parameter . Name ?? string . Empty , fromBodyAttribute . AllowEmpty , parameter . ParameterType ) ;
241
252
}
253
+ else if ( attributes . OfType < IFromFormMetadata > ( ) . FirstOrDefault ( ) is { } fromFormAttribute )
254
+ {
255
+ return ( BindingSource . FormFile , fromFormAttribute . Name ?? parameter . Name ?? string . Empty , false , parameter . ParameterType ) ;
256
+ }
242
257
else if ( parameter . CustomAttributes . Any ( a => typeof ( IFromServiceMetadata ) . IsAssignableFrom ( a . AttributeType ) ) ||
243
258
parameter . ParameterType == typeof ( HttpContext ) ||
244
259
parameter . ParameterType == typeof ( HttpRequest ) ||
@@ -265,6 +280,10 @@ private static ParameterDescriptor CreateParameterDescriptor(ParameterInfo param
265
280
return ( BindingSource . Query , parameter . Name ?? string . Empty , false , displayType ) ;
266
281
}
267
282
}
283
+ else if ( parameter . ParameterType == typeof ( IFormFile ) || parameter . ParameterType == typeof ( IFormFileCollection ) )
284
+ {
285
+ return ( BindingSource . FormFile , parameter . Name ?? string . Empty , false , parameter . ParameterType ) ;
286
+ }
268
287
else
269
288
{
270
289
return ( BindingSource . Body , parameter . Name ?? string . Empty , false , parameter . ParameterType ) ;
0 commit comments