@@ -142,6 +142,7 @@ public virtual void OnProvidersExecuted( ApiDescriptionProviderContext context )
142142 else
143143 {
144144 UpdateModelTypes ( result , matched ) ;
145+ UpdateFunctionCollectionParameters ( result , matched ) ;
145146 }
146147 }
147148
@@ -456,6 +457,75 @@ private void UpdateModelTypes( ApiDescription description, IODataRoutingMetadata
456457 }
457458 }
458459
460+ private static void UpdateFunctionCollectionParameters ( ApiDescription description , IODataRoutingMetadata metadata )
461+ {
462+ var parameters = description . ParameterDescriptions ;
463+
464+ if ( parameters . Count == 0 )
465+ {
466+ return ;
467+ }
468+
469+ var function = default ( IEdmFunction ) ;
470+ var mapping = default ( IDictionary < string , string > ) ;
471+
472+ for ( var i = 0 ; i < metadata . Template . Count ; i ++ )
473+ {
474+ var segment = metadata . Template [ i ] ;
475+
476+ if ( segment is FunctionSegmentTemplate func )
477+ {
478+ function = func . Function ;
479+ mapping = func . ParameterMappings ;
480+ break ;
481+ }
482+ else if ( segment is FunctionImportSegmentTemplate import )
483+ {
484+ function = import . FunctionImport . Function ;
485+ mapping = import . ParameterMappings ;
486+ break ;
487+ }
488+ }
489+
490+ if ( function is null || mapping is null )
491+ {
492+ return ;
493+ }
494+
495+ var name = default ( string ) ;
496+
497+ foreach ( var parameter in function . Parameters )
498+ {
499+ if ( parameter . Type . IsCollection ( ) &&
500+ mapping . TryGetValue ( parameter . Name , out name ) &&
501+ parameters . SingleOrDefault ( p => p . Name == name ) is { } param )
502+ {
503+ param . Source = BindingSource . Path ;
504+ break ;
505+ }
506+ }
507+
508+ var path = description . RelativePath ;
509+
510+ if ( string . IsNullOrEmpty ( name ) || string . IsNullOrEmpty ( path ) )
511+ {
512+ return ;
513+ }
514+
515+ var span = name . AsSpan ( ) ;
516+ Span < char > oldValue = stackalloc char [ name . Length + 2 ] ;
517+ Span < char > newValue = stackalloc char [ name . Length + 4 ] ;
518+
519+ newValue [ 1 ] = oldValue [ 0 ] = '{' ;
520+ newValue [ ^ 2 ] = oldValue [ ^ 1 ] = '}' ;
521+ newValue [ 0 ] = '[' ;
522+ newValue [ ^ 1 ] = ']' ;
523+ span . CopyTo ( oldValue . Slice ( 1 , name . Length ) ) ;
524+ span . CopyTo ( newValue . Slice ( 2 , name . Length ) ) ;
525+
526+ description . RelativePath = path . Replace ( oldValue . ToString ( ) , newValue . ToString ( ) , Ordinal ) ;
527+ }
528+
459529 private sealed class ApiDescriptionComparer : IEqualityComparer < ApiDescription >
460530 {
461531 private readonly IEqualityComparer < string ? > comparer = StringComparer . OrdinalIgnoreCase ;
0 commit comments