@@ -513,9 +513,7 @@ private static Expression CollectSourcePropertyValue(IHttpActionDescriptor actio
513513 for ( int i = 0 ; i < parts . Length ; i ++ )
514514 {
515515 string propertyName = parts [ i ] ;
516- if ( propertyName == SelfPropertyName )
517- continue ;
518-
516+ bool isNestedEnumerablePair = IsNestedEnumerablePair ( value ) ;
519517 bool isItemParameter = parameter . Items != null ;
520518 bool isNestedProperty = i > 0 ;
521519 bool hasNestedProperties = parts . Length > 1 ;
@@ -527,12 +525,14 @@ private static Expression CollectSourcePropertyValue(IHttpActionDescriptor actio
527525 {
528526 Expression sourcePropertyExpression = null ;
529527 Type resultEnumerableType = null ;
528+ bool isNestedEnumerable = false ;
530529 if ( isNestedProperty )
531530 {
532531 Type propertyEnumerableType = TryGetEnumerableType ( value . Type ) ;
533532 if ( propertyEnumerableType != null )
534533 {
535534 sourcePropertyExpression = BuildFlattenNestedEnumerableExpression ( value , propertyEnumerableType , propertyPath , parts , i , out resultEnumerableType ) ;
535+ isNestedEnumerable = true ;
536536
537537 // Skip to the end since we've processed the entire enumerable path
538538 i = parts . Length - 1 ;
@@ -553,15 +553,14 @@ private static Expression CollectSourcePropertyValue(IHttpActionDescriptor actio
553553 }
554554
555555 resultEnumerableType ??= GetEnumerableType ( sourcePropertyExpression . Type ) ;
556- value = CollectItemsParameterValue ( action , requestParameter , argumentsParameter , dependencyResolverParameter , actionParameter , compilationContext , parameter , sourcePropertyExpression , resultEnumerableType , sourceMap , ensureNullPropagation ) ;
556+ value = CollectItemsParameterValue ( action , requestParameter , argumentsParameter , dependencyResolverParameter , actionParameter , compilationContext , parameter , sourcePropertyExpression , resultEnumerableType , sourceMap , ensureNullPropagation , isNestedEnumerable ) ;
557557 }
558558 else
559559 {
560- bool isNestedEnumerablePair = IsNestedEnumerablePair ( value ) ;
561560 if ( isNestedEnumerablePair )
562561 nestedEnumerableAnchor = value ;
563562
564- CollectSourcePropertyValue ( propertyName , previousPropertyName , nestedEnumerableAnchor , ref value , ref nullCheckTarget ) ;
563+ CollectSourcePropertyValue ( propertyName , previousPropertyName , isNestedEnumerablePair , nestedEnumerableAnchor , ref value , ref nullCheckTarget ) ;
565564 }
566565
567566 if ( ensureNullPropagation && nullCheckTarget != null && i + 1 < parts . Length )
@@ -579,18 +578,21 @@ private static Expression CollectSourcePropertyValue(IHttpActionDescriptor actio
579578
580579 return value ;
581580 }
582- private static void CollectSourcePropertyValue ( string propertyName , string previousPropertyName , Expression nestedEnumerableAnchor , ref Expression value , ref Expression nullCheckTarget )
581+ private static void CollectSourcePropertyValue ( string propertyName , string previousPropertyName , bool isNestedEnumerablePair , Expression nestedEnumerableAnchor , ref Expression value , ref Expression nullCheckTarget )
583582 {
584583 switch ( propertyName )
585584 {
586585 case ItemParameterSource . ParentPropertyName :
587586 value = Expression . Property ( value , nameof ( NestedEnumerablePair < object , object > . Parent ) ) ;
588587 break ;
589588
590- case ItemParameterSource . ChildPropertyName :
589+ case SelfPropertyName when isNestedEnumerablePair :
591590 value = Expression . Property ( value , nameof ( NestedEnumerablePair < object , object > . Child ) ) ;
592591 break ;
593592
593+ case SelfPropertyName :
594+ break ;
595+
594596 case ItemParameterSource . IndexPropertyName :
595597 {
596598 if ( nestedEnumerableAnchor == null )
@@ -599,16 +601,15 @@ private static void CollectSourcePropertyValue(string propertyName, string previ
599601 string indexPropertyName = previousPropertyName switch
600602 {
601603 ItemParameterSource . ParentPropertyName => nameof ( NestedEnumerablePair < object , object > . ParentIndex ) ,
602- ItemParameterSource . ChildPropertyName => nameof ( NestedEnumerablePair < object , object > . ChildIndex ) ,
603- _ => throw new InvalidOperationException ( $ "Property '{ ItemParameterSource . IndexPropertyName } ' cannot be accessed on type '{ value . Type } '")
604+ _ => nameof ( NestedEnumerablePair < object , object > . ChildIndex ) ,
604605 } ;
605606 value = Expression . Property ( nestedEnumerableAnchor , indexPropertyName ) ;
606607 break ;
607608 }
608609
609610 default :
610611 {
611- if ( IsNestedEnumerablePair ( value ) )
612+ if ( isNestedEnumerablePair )
612613 {
613614 value = Expression . Property ( value , nameof ( NestedEnumerablePair < object , object > . Child ) ) ;
614615 }
@@ -632,6 +633,7 @@ IHttpActionDescriptor action
632633 , Type itemType
633634 , IDictionary < string , Expression > sourceMap
634635 , bool ensureNullPropagation
636+ , bool isNestedEnumerable
635637 )
636638 {
637639 Guard . IsNotNull ( itemType , nameof ( itemType ) ) ;
@@ -647,7 +649,7 @@ IHttpActionDescriptor action
647649 {
648650 HttpParameterInfo itemParameter ;
649651 ParameterExpression itemSourceVariable ;
650- if ( itemSource . SourceKind == HttpParameterSourceKind . SourceProperty && itemSource . Source . PropertyPath == ItemParameterSource . IndexPropertyName ) // ITEM.$INDEX => i
652+ if ( itemSource . SourceKind == HttpParameterSourceKind . SourceProperty && itemSource . Source . PropertyPath == ItemParameterSource . IndexPropertyName && ! isNestedEnumerable ) // ITEM.$INDEX => i
651653 {
652654 HttpParameterSourceInfo source = new HttpParameterSourceInfo ( action , requestParameter , argumentsParameter , dependencyResolverParameter , actionParameter , compilationContext , sourceMap , ItemSourceName , sourceProvider : null , propertyPath : null ) ;
653655 itemParameter = HttpParameterInfo . SourceInstance ( itemSource . ParameterType , itemSource . InternalParameterName , source ) ;
0 commit comments