OData / AspNetCoreOData

ASP.NET Core OData: A server library built upon ODataLib and ASP.NET Core
Other
457 stars 157 forks source link

Default Expanding of Navigation Properties in OData v9 for Complex Types #1328

Open KavyaNelli opened 6 days ago

KavyaNelli commented 6 days ago

Assemblies affected v9 Describe the bug I’m working with OData v9 and am currently facing an issue when trying to return a complex type from an OData function that includes a navigation property.

Scenario: I have defined a complex type Address in my EDM, which includes a navigation property PersonDetails that links to the PersonDetails entity. The PersonDetails entity further includes a collection navigation property to Orders. Reproduce steps The simplest set of steps to reproduce the issue. If possible, reference a commit that demonstrates the issue.

Data Model Model Definition: builder.ComplexType<Address>();

EDM Metadata:

<Function Name="AddressLevel" IsBound="true">
            <Parameter Name="bindingParameter" Type="Eis.PersonDetails" />
            <ReturnType Type="Collection(Eis.PersonDetails)" />
</Function>
<ComplexType Name="Address">
            <Property Name="PinCode" Type="Edm.Int32" Nullable="false" />
            <NavigationProperty Name="PersonDetails" Type="Eis.PersonDetails" />
</ComplexType>
<EntityType Name="PersonDetails">
            <Key>
                <PropertyRef Name="PersonNumber" />
            </Key>
            <Property Name="PersonNumber" Type="Edm.String" Nullable="false" />
            <Property Name="FirstName" Type="Edm.String" Nullable="false" />
            <NavigationProperty Name="Orders" Type="Collection(Eis.Orders)" />
</EntityType>
<EntityType Name="Orders">
            <Key>
                <PropertyRef Name="OrderNumber" />
            </Key>
            <Property Name="OrderNumber" Type="Edm.String" Nullable="false" />
            <Property Name="Cost" Type="Edm.Int32" Nullable="false" />
</EntityType>

I am overriding the EnableQueryAttribute to attempt to customize the default behavior to expand PersonDetails and Orders.   

By default, only PinCode is fetched.

[
    {
        "PinCode": 32451
    },
    {
        "PinCode": 2351
    }
]

When I modify my EDM as below, entire personDetails is expanding(we want only few fields to expand) and yet Orders unexpanded.

Updated Model Definition:

builder.ComplexType<Address>().ContainsRequired(p => p.PersonDetails).AutoExpand = true;

Output:

[
{
    "PersonDetails": {
        "PersonNumber": "5255",
        //all other properties of personDetails
    },
    "PinCode": 52002
},
{
    "PersonDetails": {
        "PersonNumber": "5435",
        //all other properties of personDetails
    },
    "PinCode": 54213
}
]

Expected Output:

[
{
    "PersonDetails": {
        "Orders": [
            {
                "OrderNumber": "E528155",
                "Cost": 2345,
            }
        ],
        "PersonNumber": "5255",
        "FirstName": "Jack",
    },
    "PinCode": 52002
},
{
    "PersonDetails": {
        "Orders": [
            {
                "OrderNumber": "E528155",
                "Cost": 213
            }
        ],
        "PersonNumber": "5435",
        "FirstName": "Phill",
    },
    "PinCode": 54213
}
]

I have referred to below links for insights into this limitation, but I'm open to any other suggestions or workarounds that might help achieve the expected output.

[https://github.com/OData/WebApi/issues/2669] [https://github.com/OData/AspNetCoreOData/issues/1275]

julealgon commented 6 days ago

I'm a bit confused by your "current" vs "expected". You want just some properties of PersonDetails to appear, even if they are not navigation properties?

Can you add a full example with all properties you are getting vs what you want?

Keep in mind "expand" is only about navigations. If you want other properties to not show that are not navigations you are now talking about "select", which is different.

KavyaNelli commented 6 days ago

You can ignore my commented line Current:

[
{
    "PersonDetails": {
        "PersonNumber": "5255",
        "FirstName": "Jack"
    },
    "PinCode": 52002
},
{
    "PersonDetails": {
        "PersonNumber": "5435",
        "FirstName": "Phill"
    },
    "PinCode": 54213
}
]

Expected Output:

[
{
    "PersonDetails": {
        "Orders": [
            {
                "OrderNumber": "E528155",
                "Cost": 2345,
            }
        ],
        "PersonNumber": "5255",
        "FirstName": "Jack"
    },
    "PinCode": 52002
},
{
    "PersonDetails": {
        "Orders": [
            {
                "OrderNumber": "E528155",
                "Cost": 213
            }
        ],
        "PersonNumber": "5435",
        "FirstName": "Phill",
    },
    "PinCode": 54213
}
]

I want my orders entity in my personDetails to be expanded by default

WanjohiSammy commented 6 days ago

@KavyaNelli Try the following:

  1. Add this line of code:

    builder.EntityType<PersonDetails>().ContainsRequired(p => p.Orders).AutoExpand = true;
  2. Add [AutoExpand] attribute on top of property Orders autoexpand-attribute

  3. Use $expand query option

KavyaNelli commented 4 days ago

Adding this line builder.EntityType().ContainsRequired(p => p.Orders).AutoExpand = true;

is not expanding my orders(suspecting that my Address is a complex type)

And we also have many nested entites hence we donot want to go with this approach, because doing it at every level will be difficult.

Adding [AutoExpand] for Orders will expand all the properties, we have other endpoints where we dont want to expand all the properties.