Fix navigation property expansion from function imports#2891
Draft
Fix navigation property expansion from function imports#2891
Conversation
- Modified ConvertPath to return path.Path directly for all paths - Removed IsOperationPath and GeneratePath methods as they are no longer needed - This fixes the issue where expanding navigation properties from function import results would fail with "The Path property in ODataMessageWriterSettings.ODataUri must be set when writing contained elements" Co-authored-by: habbes <8460169+habbes@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Fix navigation property expansion for GetAppStats function
Fix navigation property expansion from function imports
Nov 19, 2025
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Issues
This pull request fixes #2980.
Description
Function import requests with expanded navigation properties fail with
ODataException: The Path property in ODataMessageWriterSettings.ODataUri must be set when writing contained elements:Root cause:
ConvertPath()inODataOutputFormatterHelper.cswas discarding path segments after operation imports, causing ODL to serialize with an empty path.Changes:
ConvertPath()to always returnpath.Pathdirectly (removes 72 lines)IsOperationPath()andGeneratePath()helper methodsThis aligns with AspNetCoreOData 8+ behavior which doesn't perform path conversion.
Checklist (Uncheck if it is not completed)
Additional work necessary
None. Tests require .NET Core 3.1 runtime which is not available in the CI environment, but build succeeds and tests are correctly structured.
Original prompt
This section details on the original issue you should resolve
<issue_title>Cannot expand navigation property from entity collection returned from function import.</issue_title>
<issue_description>
If you have a composable unbound function
GetAppStatsthat returns a collection of entitiesAppUsage, and you make a request that expands navigation properties of the entity type, like so:GET /GetAppUsage()/{appId}?$expand=CredentialsGET /GetAppSuage()/{appId}/CredentialsThen you'll get an exception like the following:
Reproducing the error
Here's a link to a sample repro project I created on a fork of this repo to make it easier to demonstrate the error.
Run the project then execute the following request and check the debug output logs to see the error
GET http://localhost:5287/odata/GetAppUsage()/App1?$expand=KeyCredentialsError details and root cause
The error is thrown by
ODataWriterCore.EnterScopein ODL when serializing an expanded navigation property when the navigation property is contained and the OData path is empty (has no segments):But why is the ODataPath empty at this point despite that our request url definitely has path segments?
Well, it turns out the issue is that WebAPI 7.x has a different
ODataPathtype from ODL'sODataPath. And when it starts serialization, it converts its ODataPath to ODL's ODataPath. During the conversion, it sets the path to null if it contains an operation segment: