odata.net icon indicating copy to clipboard operation
odata.net copied to clipboard

Potential regression causes exception when calling $select against stream type

Open habbes opened this issue 2 years ago • 0 comments

Let's assume we have URL where the last segment is a stream property, and it has a $select query option:

/People(1)/StreamProp?$select=...

Then we parse this url with parser.ParseUri() or parser.ParseSelectAndExpand.

In 7.10.0, this parse works successfully

In 7.11.0 the parse fails with the following exception message:

The type 'Edm.Stream' is not valid for $select or $expand, only structured types are allowed. ---> Microsoft.OData.ODataException: The type 'Edm.Stream' is not valid for $select or $expand, only structured types are allowed.

According the spec, expanding a stream property is allowed: https://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part2-url-conventions.html#sec_SystemQueryOptionexpand But that seems to refer to when the property is part of the expand path: $expand=StreamProperty. Not sure if it also applies when the stream property is the last segment of the resource URL.

I'm not sure this is actually a bug. But this has caused a test case to fail when migrating AGS from ODL 7.10.0

Assemblies affected

Microsoft.OData.Core 7.11.0 and later

Reproduce steps

Create a model with an entity type that has a stream property (in this case Assignment):

var model = new EdmModel();
var classType = model.AddEntityType("Models", "Class");
var assignmentType = model.AddEntityType("Models", "Assignment");
var classId = classType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.String);
classType.AddKeys(classId);

var assgnId = assignmentType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.String);
assignmentType.AddKeys(assgnId);
assignmentType.AddStructuralProperty("Name", EdmPrimitiveTypeKind.String);
assignmentType.AddStructuralProperty("StreamProp", EdmPrimitiveTypeKind.Stream);

classType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo()
{
    Name = "Assignments",
    Target = assignmentType,
    TargetMultiplicity = EdmMultiplicity.Many,
    ContainsTarget = false
});

var container = model.AddEntityContainer("Models", "Container");
container.AddEntitySet("classes", classType);
container.AddEntitySet("assignments", assignmentType);

Parse a URL where the stream property is the last segment, and there's a $select option (the value of the select doesn't happen):

var parser = new ODataUriParser(model, new Uri("classes('id')/Assignments('id')/StreamProp?$select=StreamProp", UriKind.Relative));
ODataUri path = parser.ParseUri();

Expected result

It should not throw an exception.

Actual result

It throws an ODataException

Additional detail

The exception is thrown in the ODataUriQueryOptionParser.ParseSelectAndExpand method. When running the scenario above in 7.10.0, this.targetEdmType evaluates to Assignment, but in 7.11.0 it evaluates to Edm.Stream.

habbes avatar Aug 17 '22 14:08 habbes