diff --git a/src/Microsoft.OData.Core/UriParser/Parsers/ODataPathParser.cs b/src/Microsoft.OData.Core/UriParser/Parsers/ODataPathParser.cs index ea4dddee7e..107597b53b 100644 --- a/src/Microsoft.OData.Core/UriParser/Parsers/ODataPathParser.cs +++ b/src/Microsoft.OData.Core/UriParser/Parsers/ODataPathParser.cs @@ -1162,6 +1162,7 @@ private bool TryCreateTypeNameSegment(ODataPathSegment previous, string identifi [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "IEdmModel", Justification = "The spelling is correct.")] private void CreatePropertySegment(ODataPathSegment previous, IEdmProperty property, string queryPortion) { + Debug.Assert(previous != null, "previous != null"); if (property.Type.IsStream()) { // The server used to allow arbitrary key expressions after named streams because this check was missing. @@ -1180,7 +1181,11 @@ private void CreatePropertySegment(ODataPathSegment previous, IEdmProperty prope if (property.PropertyKind == EdmPropertyKind.Navigation) { var navigationProperty = (IEdmNavigationProperty)property; - IEdmNavigationSource navigationSource = previous.TargetEdmNavigationSource.FindNavigationTarget(navigationProperty); + IEdmNavigationSource navigationSource = null; + if (previous.TargetEdmNavigationSource != null) + { + navigationSource = previous.TargetEdmNavigationSource.FindNavigationTarget(navigationProperty); + } // Relationship between TargetMultiplicity and navigation property: // 1) EdmMultiplicity.Many <=> collection navigation property diff --git a/src/Microsoft.OData.Core/UriParser/SemanticAst/ODataPathSegment.cs b/src/Microsoft.OData.Core/UriParser/SemanticAst/ODataPathSegment.cs index abc09e0020..5f8e1a72ed 100644 --- a/src/Microsoft.OData.Core/UriParser/SemanticAst/ODataPathSegment.cs +++ b/src/Microsoft.OData.Core/UriParser/SemanticAst/ODataPathSegment.cs @@ -91,7 +91,8 @@ internal void AssertValid() Debug.Assert(Enum.IsDefined(typeof(RequestTargetKind), this.TargetKind), "enum value is not valid"); Debug.Assert( this.TargetKind != RequestTargetKind.Resource || - this.TargetEdmNavigationSource != null || + this.TargetEdmNavigationSource != null || + this.TargetEdmType != null || this.TargetKind == RequestTargetKind.OpenProperty || this is OperationSegment || this is OperationImportSegment, diff --git a/test/FunctionalTests/Microsoft.OData.Core.Tests/UriParser/ODataUriParserTests.cs b/test/FunctionalTests/Microsoft.OData.Core.Tests/UriParser/ODataUriParserTests.cs index b337c5679d..c96cea9d4e 100644 --- a/test/FunctionalTests/Microsoft.OData.Core.Tests/UriParser/ODataUriParserTests.cs +++ b/test/FunctionalTests/Microsoft.OData.Core.Tests/UriParser/ODataUriParserTests.cs @@ -512,5 +512,56 @@ public void ParseCompositeKeyReference(TestUrlConvention testUrlConvention, stri } #endregion + + #region Null EntitySetPath + + [Fact] + public void ParsePathFunctionWithNullEntitySetPath() + { + var model = new EdmModel(); + + var customer = new EdmEntityType("Test", "Customer", null, false, false); + var customerId = customer.AddStructuralProperty("id", EdmPrimitiveTypeKind.String, false); + customer.AddKeys(customerId); + model.AddElement(customer); + + var detail = new EdmEntityType("Test", "Detail", null, false, true); + detail.AddStructuralProperty("address", EdmPrimitiveTypeKind.String, true); + model.AddElement(detail); + + var customerDetail = customer.AddUnidirectionalNavigation( + new EdmNavigationPropertyInfo() + { + Name = "detail", + Target = detail, + TargetMultiplicity = EdmMultiplicity.One, + ContainsTarget = true + }); + + // The test is to make sure the ODataUriParser works even though + // the entitySetPathExpression is null. + var getCurrentCustomer = new EdmFunction( + "Test", + "getCurrentCustomer", + new EdmEntityTypeReference(customer, false), + isBound: false, + entitySetPathExpression: null, + isComposable: true); + model.AddElement(getCurrentCustomer); + + var container = new EdmEntityContainer("Test", "Container"); + var getCurrentCustomerImport = container.AddFunctionImport(getCurrentCustomer); + model.AddElement(container); + + var parser = new ODataUriParser(model, new Uri("http://host"), new Uri("http://host/getCurrentCustomer()/detail")); + var path = parser.ParsePath(); + var pathSegmentList = path.ToList(); + pathSegmentList.Count.Should().Be(2); + pathSegmentList[0].ShouldBeOperationImportSegment(getCurrentCustomerImport); + pathSegmentList[1].ShouldBeNavigationPropertySegment(customerDetail); + } + + #endregion + } }