From 5bb59c6209ea9e4dfa8d8851b20a404f0e58b54f Mon Sep 17 00:00:00 2001 From: Lingxi-Li Date: Wed, 24 Aug 2016 13:36:53 +0800 Subject: [PATCH] Fix bug: unqualified type name is treated as type-cast #680 --- .../UriParser/Parsers/ODataPathParser.cs | 11 ++++++----- .../UriParser/Metadata/ODataUriResolverTests.cs | 16 ++++++++++++++++ 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.OData.Core/UriParser/Parsers/ODataPathParser.cs b/src/Microsoft.OData.Core/UriParser/Parsers/ODataPathParser.cs index 107597b53b..ad3c7b3ffd 100644 --- a/src/Microsoft.OData.Core/UriParser/Parsers/ODataPathParser.cs +++ b/src/Microsoft.OData.Core/UriParser/Parsers/ODataPathParser.cs @@ -67,7 +67,7 @@ internal ODataPathParser(ODataUriParserConfiguration configuration) } /// - /// Extracts the segment identifier and, if there are parenthesis in the segment, the expression in the parenthesis. + /// Extracts the segment identifier and, if there are parenthesis in the segment, the expression in the parenthesis. /// Will throw if identifier is not found or if the parenthesis expression is malformed. /// /// Internal only so it can be called from tests. Should not be used outside . @@ -375,10 +375,10 @@ private bool TryGetNextSegmentText(bool previousSegmentWasEscapeMarker, out stri // If this segment is the special escape-marker segment, then remember that the next segment cannot be a key, // even if we are in key-as-segments mode. Essentially, it is an escape into 'metadata-space', so to speak. - // + // // DEVNOTE (mmeehan): We went back and forth several times on whether this should be allowed everywhere or only // where a key could appear. We landed on allowing it absolutely everywhere for several reasons: - // 1) The WCF DS client naively adds the escape marker before all type segments, regardless of whether the + // 1) The WCF DS client naively adds the escape marker before all type segments, regardless of whether the // prior segment is a collection. // 2) The WCF DS server already allowed the escape marker almost everywhere in 5.3 // 3) It's better to be either extremely loose or extremely strict than allow it in some cases and not in others. @@ -688,7 +688,7 @@ private void CreateOpenPropertySegment(ODataPathSegment previous, string identif { ODataPathSegment segment = new OpenPropertySegment(identifier); - // Handle an open type property. If the current leaf isn't an + // Handle an open type property. If the current leaf isn't an // object (which implies it's already an open type), then // it should be marked as an open type. if (previous.TargetEdmType != null && !previous.TargetEdmType.IsOpenType()) @@ -1023,7 +1023,8 @@ private void CreateNextSegment(string text) // If the property resolution failed, and the previous segment was targeting an entity, then we should // try and resolve the identifier as type name. - if (this.TryCreateTypeNameSegment(previous, identifier, parenthesisExpression)) + if (text.IndexOf('.') >= 0 && // type-cast should use qualified type names + this.TryCreateTypeNameSegment(previous, identifier, parenthesisExpression)) { return; } diff --git a/test/FunctionalTests/Microsoft.OData.Core.Tests/UriParser/Metadata/ODataUriResolverTests.cs b/test/FunctionalTests/Microsoft.OData.Core.Tests/UriParser/Metadata/ODataUriResolverTests.cs index 9d4ce3aca7..baa68b2e80 100644 --- a/test/FunctionalTests/Microsoft.OData.Core.Tests/UriParser/Metadata/ODataUriResolverTests.cs +++ b/test/FunctionalTests/Microsoft.OData.Core.Tests/UriParser/Metadata/ODataUriResolverTests.cs @@ -267,6 +267,22 @@ public void TestStringAsEnumInNamedKey() } #endregion + [Fact] + public void UnqualifiedTypeNameShouldNotBeTreatedAsTypeCast() + { + var model = new EdmModel(); + var entityType = new EdmEntityType("NS", "Entity"); + entityType.AddKeys(entityType.AddStructuralProperty("IdStr", EdmPrimitiveTypeKind.String, false)); + var container = new EdmEntityContainer("NS", "Container"); + var set = container.AddEntitySet("Set", entityType); + model.AddElements(new IEdmSchemaElement[] { entityType, container }); + + var svcRoot = new Uri("http://host", UriKind.Absolute); + var parser = new ODataUriParser(model, svcRoot, new Uri("http://host/Set/Date", UriKind.Absolute)); + parser.UrlConventions = ODataUrlConventions.KeyAsSegment; + var parseResult = parser.ParseUri(); + Assert.True(parseResult.Path.LastSegment is KeySegment); + } [Fact] public void CaseInsensitiveEntitySetKeyNamePositional()