Skip to content

Commit

Permalink
Added handling for derived types, dynamic properties, and missing nav…
Browse files Browse the repository at this point in the history
…igation property bindings.

Added tests for above
  • Loading branch information
mikepizzo committed Jan 19, 2023
1 parent 817a509 commit e72ad11
Show file tree
Hide file tree
Showing 3 changed files with 266 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,9 @@

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Reflection;
using Microsoft.AspNet.OData.Extensions;
using Microsoft.AspNet.OData.Interfaces;
using Microsoft.OData;
using Microsoft.OData.Edm;
Expand Down Expand Up @@ -68,7 +66,6 @@ internal static ODataDeserializerContext GenerateNestedReadContext(ODataNestedRe
segmentType = readContext.Model.FindType(propertyTypeName);
}

// could it be a problem later that the navigationSource is null?
DynamicPathSegment pathSegment = new DynamicPathSegment(
nestedResourceInfo.Name,
segmentType,
Expand All @@ -81,13 +78,12 @@ internal static ODataDeserializerContext GenerateNestedReadContext(ODataNestedRe
{
if (edmProperty.PropertyKind == EdmPropertyKind.Navigation)
{
Contract.Assert(readContext.Path.NavigationSource != null, "Navigation property segment with null navigationSource");
IEdmNavigationProperty navigationProperty = edmProperty as IEdmNavigationProperty;
IEdmNavigationSource parentNavigationSource = readContext.Path.NavigationSource;
IEdmPathExpression bindingPath = GetBindingPath(readContext.Path, navigationProperty.Name);
IEdmNavigationSource navigationSource = parentNavigationSource.FindNavigationTarget(navigationProperty, bindingPath);
IEdmPathExpression bindingPath = GetBindingPath(readContext.Path, navigationProperty);
IEdmNavigationSource navigationSource = parentNavigationSource?.FindNavigationTarget(navigationProperty, bindingPath);

if (navigationProperty.ContainsTarget)
if (navigationProperty.ContainsTarget || navigationSource == null || navigationSource is IEdmUnknownEntitySet)
{
path = AppendToPath(path, new NavigationPropertySegment(navigationProperty, navigationSource), navigationProperty.DeclaringType, parentNavigationSource);
}
Expand All @@ -114,21 +110,20 @@ internal static ODataDeserializerContext GenerateNestedReadContext(ODataNestedRe
}

// Determines the binding path for an OData Path to a given navigationProperty
private static IEdmPathExpression GetBindingPath(Routing.ODataPath path, string navPropName)
private static IEdmPathExpression GetBindingPath(Routing.ODataPath path, IEdmNavigationProperty navigationProperty)
{
List<string> segments = new List<string>();

Contract.Assert(navigationProperty != null, "Called GetBindingPath with a null navigation property");
if (path == null)
{
return null;
}

// Binding Path is made up of complex types, containment navigation properties, and type segments
List<string> segments = new List<string>();
foreach (ODataPathSegment segment in path.Segments)
{
if (segment is NavigationPropertySegment navSegment)
{
Debug.Assert(navSegment.NavigationProperty.ContainsTarget, "Non-contained navigation property in binding path");
segments.Add(navSegment.NavigationProperty.Name);
}
else if (segment is PropertySegment propertySegment)
Expand All @@ -141,7 +136,13 @@ private static IEdmPathExpression GetBindingPath(Routing.ODataPath path, string
}
}

segments.Add(navPropName);
if(navigationProperty.DeclaringType != path.EdmType as IEdmStructuredType)
{
// Add a type cast segment
segments.Add(navigationProperty.DeclaringType.FullTypeName());
}

segments.Add(navigationProperty.Name);

return new EdmPathExpression(String.Join("/", segments));
}
Expand Down Expand Up @@ -190,11 +191,13 @@ internal static Routing.ODataPath AppendToPath(Routing.ODataPath path, ODataPath
}

List<ODataPathSegment> segments = new List<ODataPathSegment>(path.Segments);
IEdmType pathType = path.EdmType;

// Append type cast segment if required
if (declaringType != null && path.EdmType != declaringType)
if (declaringType != null && pathType != null && pathType != declaringType
&& declaringType.IsOrInheritsFrom(pathType.AsElementType()))
{
segments.Add(new TypeSegment(declaringType, navigationSource));
segments.Add(new TypeSegment(declaringType, pathType, navigationSource));
}

segments.Add(segment);
Expand Down
Loading

0 comments on commit e72ad11

Please sign in to comment.