Skip to content

Conversation

Copy link

Copilot AI commented Nov 25, 2025

Issues

This pull request fixes #3447.

Description

The reported issue described ArgumentNullException when parsing nested $filter or $orderby in $expand for unbound functions without entity set path:

GET /GetActiveCustomers()?$expand=Orders($filter=TotalPrice gt 1000)

Investigation findings: The current implementation in SelectExpandBinder.CreateBindingState already handles this correctly. The condition if (targetNavigationSource == null && elementType == null) only returns null when both are null. In expand scenarios, elementType is always derived from the navigation property type, so binding proceeds successfully even without navigation sources.

Changes: Added 4 regression tests to prevent future regressions:

  • ExpandWithNestedFilterWorksWithoutEntitySet
  • ExpandWithNestedOrderByWorksWithoutEntitySet
  • ExpandWithNestedFilterAndOrderByWorksWithoutEntitySet
  • NestedExpandWithFilterWorksWithoutEntitySet

Checklist (Uncheck if it is not completed)

  • Test cases added
  • Build and test with one-click build and test script passed

Additional work necessary

None required.

Repository notes

Team members can start a CI build by adding a comment with the text /AzurePipelines run to a PR. A bot may respond indicating that there is no pipeline associated with the pull request. This can be ignored if the build is triggered.

Team members should not trigger a build this way for pull requests coming from forked repositories. They should instead trigger the build manually by setting the "branch" to refs/pull/{prId}/merge where {prId} is the ID of the PR.

Original prompt

This section details on the original issue you should resolve

<issue_title>Parsing nested $filter in $expand fails if request path does not have a navigation source.</issue_title>
<issue_description>

Describe the bug

Let's say you have a schema with a top-level unbound function import that does not have an entity set path, the function is composable and returns a collection of entities (but not bound to an entity set).

If you make a request to the function, then query the results using a nested $filter inside an $expand query option like so:

GET /GetActiveCustomers()?$expand=Orders($filter=TotalPrice gt 1000)

You'll get an exception like the following

System.ArgumentNullException: Value cannot be null. (Parameter 'initialState')
ExceptionUtils.CheckArgumentNotNull[T](T value, String parameterName)
MetadataBinder.ctor(BindingState initialState)
SelectExpandBinder.BuildNewMetadataBinder(ODataUriParserConfiguration config, IEdmNavigationSource resourcePathNavigationSource, IEdmNavigationSource targetNavigationSource, IEdmTypeReference elementType, HashSet`1 generatedProperties, Boolean collapsed)
SelectExpandBinder.BindFilter(QueryToken filterToken, IEdmNavigationSource resourcePathNavigationSource, IEdmNavigationSource targetNavigationSource, IEdmTypeReference elementType, HashSet`1 generatedProperties, Boolean collapsed)
SelectExpandBinder.GenerateExpandItem(ExpandTermToken tokenIn)
SelectEnumerableIterator`2.MoveNext()
WhereEnumerableIterator`1.MoveNext()
List`1.AddRange(IEnumerable`1 collection)
SelectExpandBinder.Bind(ExpandToken expandToken, SelectToken selectToken)
SelectExpandSemanticBinder.Bind(ODataPathInfo odataPathInfo, ExpandToken expandToken, SelectToken selectToken, ODataUriParserConfiguration configuration, BindingState state)
ODataQueryOptionParser.ParseSelectAndExpandImplementation(String select, String expand, ODataUriParserConfiguration configuration, ODataPathInfo odataPathInfo)
ODataQueryOptionParser.ParseSelectAndExpand()
ODataUriParser.ParseSelectAndExpand()

Here's the culprit

Image Image

Seems like it's caused by the resourcePathNavigationSource being null, causing CreateBindingState returning null, which causes the MetadataBinder constructor to throw the argument null exception.

PS: This also seems to affect nested $orderby.

Assemblies affected

Which assemblies and versions are known to be affected e.g. Microsoft.OData.Core 8.x

Steps to Reproduce

The simplest set of steps to reproduce the issue. If possible, reference a commit that demonstrates the issue.

Expected behaviour

What would happen if there wasn't a bug.

Actual behaviour

What is actually happening.

Additional details

Optional, details of the root cause if known. Delete this section if you have no additional details to add.
</issue_description>

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI changed the title [WIP] Fix parsing nested $filter in $expand for unbound functions Add regression tests for nested $filter/$orderby in $expand without entity set Nov 25, 2025
Copilot AI requested a review from marabooy November 25, 2025 14:51
Copilot finished work on behalf of marabooy November 25, 2025 14:51
@marabooy
Copy link
Member

/AzurePipelines run

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Parsing nested $filter in $expand fails if request path does not have a navigation source.

2 participants