OData / OData/AspNetCoreOData

Navigation Source in Filter ODataQueryOptions is skipping one level when querying for collection objects

Open
#688 16 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C#
Stars
505
Forks
186
PR merge metrics
No merged PRs in 30d

Description

Discussed in https://github.com/OData/AspNetCoreOData/discussions/687

Originally posted by gupta-aashika September 7, 2022
We are trying to apply a filter query on a collection object which is two-level deep in my entity. Our entity model looks like the following:

	public class MockOpenType
	{
                [DataMember(Name = "customId")]
		public string CustomId { get; set; }
		public Competitor Competitor { get; set; }
	}
	public class Competitor
	{
                [DataMember(Name = "customId")]
		public string CustomId { get; set; }
		public List<Location> Locations { get; set; }
	}
	public class Location
	{
                [DataMember(Name = "customId")]
		public string CustomId { get; set; }
		public string Name { get; set; }
	}

Here is how we are building our EDM model.

            var builder = new ODataConventionModelBuilder();
            var type = typeof(MockOpenType);
            var entityTypeConfiguration = builder.AddEntityType(type);
            entityTypeConfiguration.HasKey(type.GetProperty("CustomId"));
            builder.AddEntitySet(type.Name, entityTypeConfiguration);
            var conf = builder.EntitySet<MockOpenType>(type.Name);
            conf.EntityType.Property(p => p.CustomId).Name = "customId";
            
            var edmModels = builder.GetEdmModel();

The OData query looks like http://localhost/User?$filter=competitor/locations/any(m: m/name eq 'test')

The OData query translates into ODataQueryOptions which has NavigationSource. The navigation source is formed incorrectly. It skips the the competitor in the path. Internally the path segments for "locations" has only single value i.e. ["MockOpenType"]. It skips the "Competitor" entity. Due to this my resultant response is wrong.

Note: Due to some reason, the navigation source is formed correctly if I replace "CustomId" with "Id" and "customId" with "id". Here the path segments is created with two values ["MockOpenType", "Competitor"] and thus the filter works fine.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with discussion 687 and reproduce the nested filter using the MockOpenType, Competitor, and Location model and ODataConventionModelBuilder setup shown here. Trace how Filter ODataQueryOptions constructs NavigationSource for competitor/locations/any(...) when the key is named CustomId, then compare it with the Id case. Done means the path retains both MockOpenType and Competitor and the customId query returns the correct result.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.