@@ -149,7 +149,7 @@ private ApiDescription CreateApiDescription(RouteEndpoint routeEndpoint, string
149149
150150 private ApiParameterDescription ? CreateApiParameterDescription ( ParameterInfo parameter , RoutePattern pattern )
151151 {
152- var ( source , name , allowEmpty ) = GetBindingSourceAndName ( parameter , pattern ) ;
152+ var ( source , name , allowEmpty , paramType ) = GetBindingSourceAndName ( parameter , pattern ) ;
153153
154154 // Services are ignored because they are not request parameters.
155155 // We ignore/skip body parameter because the value will be retrieved from the IAcceptsMetadata.
@@ -166,7 +166,7 @@ private ApiDescription CreateApiDescription(RouteEndpoint routeEndpoint, string
166166 return new ApiParameterDescription
167167 {
168168 Name = name ,
169- ModelMetadata = CreateModelMetadata ( parameter . ParameterType ) ,
169+ ModelMetadata = CreateModelMetadata ( paramType ) ,
170170 Source = source ,
171171 DefaultValue = parameter . DefaultValue ,
172172 Type = parameter . ParameterType ,
@@ -176,25 +176,25 @@ private ApiDescription CreateApiDescription(RouteEndpoint routeEndpoint, string
176176
177177 // TODO: Share more of this logic with RequestDelegateFactory.CreateArgument(...) using RequestDelegateFactoryUtilities
178178 // which is shared source.
179- private ( BindingSource , string , bool ) GetBindingSourceAndName ( ParameterInfo parameter , RoutePattern pattern )
179+ private ( BindingSource , string , bool , Type ) GetBindingSourceAndName ( ParameterInfo parameter , RoutePattern pattern )
180180 {
181181 var attributes = parameter . GetCustomAttributes ( ) ;
182182
183183 if ( attributes . OfType < IFromRouteMetadata > ( ) . FirstOrDefault ( ) is { } routeAttribute )
184184 {
185- return ( BindingSource . Path , routeAttribute . Name ?? parameter . Name ?? string . Empty , false ) ;
185+ return ( BindingSource . Path , routeAttribute . Name ?? parameter . Name ?? string . Empty , false , parameter . ParameterType ) ;
186186 }
187187 else if ( attributes . OfType < IFromQueryMetadata > ( ) . FirstOrDefault ( ) is { } queryAttribute )
188188 {
189- return ( BindingSource . Query , queryAttribute . Name ?? parameter . Name ?? string . Empty , false ) ;
189+ return ( BindingSource . Query , queryAttribute . Name ?? parameter . Name ?? string . Empty , false , parameter . ParameterType ) ;
190190 }
191191 else if ( attributes . OfType < IFromHeaderMetadata > ( ) . FirstOrDefault ( ) is { } headerAttribute )
192192 {
193- return ( BindingSource . Header , headerAttribute . Name ?? parameter . Name ?? string . Empty , false ) ;
193+ return ( BindingSource . Header , headerAttribute . Name ?? parameter . Name ?? string . Empty , false , parameter . ParameterType ) ;
194194 }
195195 else if ( attributes . OfType < IFromBodyMetadata > ( ) . FirstOrDefault ( ) is { } fromBodyAttribute )
196196 {
197- return ( BindingSource . Body , parameter . Name ?? string . Empty , fromBodyAttribute . AllowEmpty ) ;
197+ return ( BindingSource . Body , parameter . Name ?? string . Empty , fromBodyAttribute . AllowEmpty , parameter . ParameterType ) ;
198198 }
199199 else if ( parameter . CustomAttributes . Any ( a => typeof ( IFromServiceMetadata ) . IsAssignableFrom ( a . AttributeType ) ) ||
200200 parameter . ParameterType == typeof ( HttpContext ) ||
@@ -205,23 +205,25 @@ private ApiDescription CreateApiDescription(RouteEndpoint routeEndpoint, string
205205 ParameterBindingMethodCache . HasBindAsyncMethod ( parameter ) ||
206206 _serviceProviderIsService ? . IsService ( parameter . ParameterType ) == true )
207207 {
208- return ( BindingSource . Services , parameter . Name ?? string . Empty , false ) ;
208+ return ( BindingSource . Services , parameter . Name ?? string . Empty , false , parameter . ParameterType ) ;
209209 }
210210 else if ( parameter . ParameterType == typeof ( string ) || ParameterBindingMethodCache . HasTryParseMethod ( parameter ) )
211211 {
212+ // complex types will display as strings since they use custom parsing via TryParse on a string
213+ var displayType = ! parameter . ParameterType . IsPrimitive ? typeof ( string ) : parameter . ParameterType ;
212214 // Path vs query cannot be determined by RequestDelegateFactory at startup currently because of the layering, but can be done here.
213215 if ( parameter . Name is { } name && pattern . GetParameter ( name ) is not null )
214216 {
215- return ( BindingSource . Path , name , false ) ;
217+ return ( BindingSource . Path , name , false , displayType ) ;
216218 }
217219 else
218220 {
219- return ( BindingSource . Query , parameter . Name ?? string . Empty , false ) ;
221+ return ( BindingSource . Query , parameter . Name ?? string . Empty , false , displayType ) ;
220222 }
221223 }
222224 else
223225 {
224- return ( BindingSource . Body , parameter . Name ?? string . Empty , false ) ;
226+ return ( BindingSource . Body , parameter . Name ?? string . Empty , false , parameter . ParameterType ) ;
225227 }
226228 }
227229
0 commit comments