@@ -66,7 +66,6 @@ internal static ODataDeserializerContext GenerateNestedReadContext(ODataNestedRe
6666 segmentType = readContext . Model . FindType ( propertyTypeName ) ;
6767 }
6868
69- // could it be a problem later that the navigationSource is null?
7069 DynamicPathSegment pathSegment = new DynamicPathSegment (
7170 nestedResourceInfo . Name ,
7271 segmentType ,
@@ -79,12 +78,12 @@ internal static ODataDeserializerContext GenerateNestedReadContext(ODataNestedRe
7978 {
8079 if ( edmProperty . PropertyKind == EdmPropertyKind . Navigation )
8180 {
82- Contract . Assert ( readContext . Path . NavigationSource != null , "Navigation property segment with null navigationSource" ) ;
8381 IEdmNavigationProperty navigationProperty = edmProperty as IEdmNavigationProperty ;
8482 IEdmNavigationSource parentNavigationSource = readContext . Path . NavigationSource ;
85- IEdmNavigationSource navigationSource = parentNavigationSource . FindNavigationTarget ( navigationProperty ) ;
83+ IEdmPathExpression bindingPath = GetBindingPath ( readContext . Path , navigationProperty ) ;
84+ IEdmNavigationSource navigationSource = parentNavigationSource ? . FindNavigationTarget ( navigationProperty , bindingPath ) ;
8685
87- if ( navigationProperty . ContainsTarget )
86+ if ( navigationProperty . ContainsTarget || navigationSource == null || navigationSource is IEdmUnknownEntitySet )
8887 {
8988 path = AppendToPath ( path , new NavigationPropertySegment ( navigationProperty , navigationSource ) , navigationProperty . DeclaringType , parentNavigationSource ) ;
9089 }
@@ -110,6 +109,44 @@ internal static ODataDeserializerContext GenerateNestedReadContext(ODataNestedRe
110109 return BuildNestedContextFromCurrentContext ( readContext , path ) ;
111110 }
112111
112+ // Determines the binding path for an OData Path to a given navigationProperty
113+ private static IEdmPathExpression GetBindingPath ( Routing . ODataPath path , IEdmNavigationProperty navigationProperty )
114+ {
115+ Contract . Assert ( navigationProperty != null , "Called GetBindingPath with a null navigation property" ) ;
116+ if ( path == null )
117+ {
118+ return null ;
119+ }
120+
121+ // Binding Path is made up of complex types, containment navigation properties, and type segments
122+ List < string > segments = new List < string > ( ) ;
123+ foreach ( ODataPathSegment segment in path . Segments )
124+ {
125+ if ( segment is NavigationPropertySegment navSegment )
126+ {
127+ segments . Add ( navSegment . NavigationProperty . Name ) ;
128+ }
129+ else if ( segment is PropertySegment propertySegment )
130+ {
131+ segments . Add ( propertySegment . Property . Name ) ;
132+ }
133+ else if ( segment is TypeSegment typeSegment )
134+ {
135+ segments . Add ( typeSegment . Identifier ) ;
136+ }
137+ }
138+
139+ if ( navigationProperty . DeclaringType != path . EdmType as IEdmStructuredType )
140+ {
141+ // Add a type cast segment
142+ segments . Add ( navigationProperty . DeclaringType . FullTypeName ( ) ) ;
143+ }
144+
145+ segments . Add ( navigationProperty . Name ) ;
146+
147+ return new EdmPathExpression ( String . Join ( "/" , segments ) ) ;
148+ }
149+
113150 /// <summary>
114151 /// It builds a nested deserializer context from the current deserializer context
115152 /// </summary>
@@ -154,11 +191,13 @@ internal static Routing.ODataPath AppendToPath(Routing.ODataPath path, ODataPath
154191 }
155192
156193 List < ODataPathSegment > segments = new List < ODataPathSegment > ( path . Segments ) ;
194+ IEdmType pathType = path . EdmType ;
157195
158196 // Append type cast segment if required
159- if ( declaringType != null && path . EdmType != declaringType )
197+ if ( declaringType != null && pathType != null && pathType != declaringType
198+ && declaringType . IsOrInheritsFrom ( pathType . AsElementType ( ) ) )
160199 {
161- segments . Add ( new TypeSegment ( declaringType , navigationSource ) ) ;
200+ segments . Add ( new TypeSegment ( declaringType , pathType , navigationSource ) ) ;
162201 }
163202
164203 segments . Add ( segment ) ;
0 commit comments