@@ -147,7 +147,7 @@ private ApiDescription CreateApiDescription(RouteEndpoint routeEndpoint, string
147147
148148 private ApiParameterDescription ? CreateApiParameterDescription ( ParameterInfo parameter , RoutePattern pattern )
149149 {
150- var ( source , name , allowEmpty ) = GetBindingSourceAndName ( parameter , pattern ) ;
150+ var ( source , name , allowEmpty , paramType ) = GetBindingSourceAndName ( parameter , pattern ) ;
151151
152152 // Services are ignored because they are not request parameters.
153153 // We ignore/skip body parameter because the value will be retrieved from the IAcceptsMetadata.
@@ -165,7 +165,7 @@ private ApiDescription CreateApiDescription(RouteEndpoint routeEndpoint, string
165165 return new ApiParameterDescription
166166 {
167167 Name = name ,
168- ModelMetadata = CreateModelMetadata ( parameter . ParameterType ) ,
168+ ModelMetadata = CreateModelMetadata ( paramType ) ,
169169 Source = source ,
170170 DefaultValue = parameter . DefaultValue ,
171171 Type = parameter . ParameterType ,
@@ -184,25 +184,25 @@ private static ParameterDescriptor CreateParameterDescriptor(ParameterInfo param
184184
185185 // TODO: Share more of this logic with RequestDelegateFactory.CreateArgument(...) using RequestDelegateFactoryUtilities
186186 // which is shared source.
187- private ( BindingSource , string , bool ) GetBindingSourceAndName ( ParameterInfo parameter , RoutePattern pattern )
187+ private ( BindingSource , string , bool , Type ) GetBindingSourceAndName ( ParameterInfo parameter , RoutePattern pattern )
188188 {
189189 var attributes = parameter . GetCustomAttributes ( ) ;
190190
191191 if ( attributes . OfType < IFromRouteMetadata > ( ) . FirstOrDefault ( ) is { } routeAttribute )
192192 {
193- return ( BindingSource . Path , routeAttribute . Name ?? parameter . Name ?? string . Empty , false ) ;
193+ return ( BindingSource . Path , routeAttribute . Name ?? parameter . Name ?? string . Empty , false , parameter . ParameterType ) ;
194194 }
195195 else if ( attributes . OfType < IFromQueryMetadata > ( ) . FirstOrDefault ( ) is { } queryAttribute )
196196 {
197- return ( BindingSource . Query , queryAttribute . Name ?? parameter . Name ?? string . Empty , false ) ;
197+ return ( BindingSource . Query , queryAttribute . Name ?? parameter . Name ?? string . Empty , false , parameter . ParameterType ) ;
198198 }
199199 else if ( attributes . OfType < IFromHeaderMetadata > ( ) . FirstOrDefault ( ) is { } headerAttribute )
200200 {
201- return ( BindingSource . Header , headerAttribute . Name ?? parameter . Name ?? string . Empty , false ) ;
201+ return ( BindingSource . Header , headerAttribute . Name ?? parameter . Name ?? string . Empty , false , parameter . ParameterType ) ;
202202 }
203203 else if ( attributes . OfType < IFromBodyMetadata > ( ) . FirstOrDefault ( ) is { } fromBodyAttribute )
204204 {
205- return ( BindingSource . Body , parameter . Name ?? string . Empty , fromBodyAttribute . AllowEmpty ) ;
205+ return ( BindingSource . Body , parameter . Name ?? string . Empty , fromBodyAttribute . AllowEmpty , parameter . ParameterType ) ;
206206 }
207207 else if ( parameter . CustomAttributes . Any ( a => typeof ( IFromServiceMetadata ) . IsAssignableFrom ( a . AttributeType ) ) ||
208208 parameter . ParameterType == typeof ( HttpContext ) ||
@@ -213,23 +213,25 @@ private static ParameterDescriptor CreateParameterDescriptor(ParameterInfo param
213213 ParameterBindingMethodCache . HasBindAsyncMethod ( parameter ) ||
214214 _serviceProviderIsService ? . IsService ( parameter . ParameterType ) == true )
215215 {
216- return ( BindingSource . Services , parameter . Name ?? string . Empty , false ) ;
216+ return ( BindingSource . Services , parameter . Name ?? string . Empty , false , parameter . ParameterType ) ;
217217 }
218218 else if ( parameter . ParameterType == typeof ( string ) || ParameterBindingMethodCache . HasTryParseMethod ( parameter ) )
219219 {
220+ // complex types will display as strings since they use custom parsing via TryParse on a string
221+ var displayType = ! parameter . ParameterType . IsPrimitive ? typeof ( string ) : parameter . ParameterType ;
220222 // Path vs query cannot be determined by RequestDelegateFactory at startup currently because of the layering, but can be done here.
221223 if ( parameter . Name is { } name && pattern . GetParameter ( name ) is not null )
222224 {
223- return ( BindingSource . Path , name , false ) ;
225+ return ( BindingSource . Path , name , false , displayType ) ;
224226 }
225227 else
226228 {
227- return ( BindingSource . Query , parameter . Name ?? string . Empty , false ) ;
229+ return ( BindingSource . Query , parameter . Name ?? string . Empty , false , displayType ) ;
228230 }
229231 }
230232 else
231233 {
232- return ( BindingSource . Body , parameter . Name ?? string . Empty , false ) ;
234+ return ( BindingSource . Body , parameter . Name ?? string . Empty , false , parameter . ParameterType ) ;
233235 }
234236 }
235237
0 commit comments