WebApi icon indicating copy to clipboard operation
WebApi copied to clipboard

MaxExpansionDepth = 0 appears to have no effect

Open xuzhg opened this issue 8 years ago • 10 comments

Copied form https://github.com/OData/odata.net/issues/860

Setting the MaxExpansionDepth to 0 appears to have no effect. Testing parent-child database classes yields the same result as not setting this attribute with: ?$expand=x($levels=max). Also when trying to set $levels to a number higher than default for example the following error is given: "Value cannot be null. Parameter name: value" suggesting it is replaced when higher than default.

Setting MaxExpansionDepth to, for example, 10 solves the problem. EDIT: Setting to 10 solves the error from appearing, but the JSON output is still a maximum of 3 levels deep! Even though the query being executed actually fetches the necessary data (confirmed by EF query logging).

Assemblies affected

Latest NuGet Microsoft.AspNet.Odata.

Reproduce steps

Create a class with parent-child relation. Set MaxExpansionDepth of the controller to 0. Notice that the expansion only works until the default allowed levels.

Expected result

I would expect setting MaxExpansionDepth = 0 would allow me to go as deep as I want in a class with parent-child relation, until the parent or child is null.

At least to me this is the result I would expect when looking at the documentation and attribute property summary.

See documentation: "Cyclic navigation properties (whose target type is identical or can be cast to its source type) can be recursively expanded using the special $levels option. The value of the $levels option is either a positive integer to specify the number of levels to expand, or the literal string max to specify the maximum expansion level supported by that service."

And attribute property summary: "Gets or sets the max expansion depth for the $expand query option. To disable the maximum expansion depth check, set this property to 0."

Actual result

MaxExpansionDepth = 0 does not disable the MaxExpansionDepth check.

Additional detail

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

xuzhg avatar Aug 28 '17 23:08 xuzhg

@xuzhg Is it possible to have an update on this?

bdebaere avatar Aug 31 '17 11:08 bdebaere

@xuzhg Any update here?

bdebaere avatar Nov 21 '17 13:11 bdebaere

@xuzhg @robward-ms The biggest issue here is that when expanding anything more than 3 levels the JSON output does not return this information. Would it be possible to get some feedback here?

bdebaere avatar Nov 30 '17 12:11 bdebaere

I was faced with a similar problem. In my case, the problem was that the property was containment navigation property.

Request: http://localhost:63773/ODataExample/Users?$expand=Orders($expand=OrderPositions($expand=Products($expand=Parameters)))

builder.EntitySet<User>("Users");
builder.EntitySet<Order>("Orders");
builder.EntitySet<OrderPosition>("OrderPositions");
builder.EntitySet<Product>("Products");

builder.EntityType<User>()
       .Expand(10, nameof(User.Orders))
       // The property will be marked as containment navigation property
       // and expanding anything more than 3 levels the JSON output does not return information
       .ContainsMany(x => x.Orders);

builder.EntityType<Order>()
       .Expand(10, nameof(Order.OrderPositions));

builder.EntityType<OrderPosition>()
       .Expand(10, nameof(OrderPosition.Products));

builder.EntityType<Product>()
       .Expand(10, nameof(Product.Parameters));
<EntityType Name="User">
  <Key>
    <PropertyRef Name="Id"/>
  </Key>
  <Property Name="Id" Type="Edm.Int64" Nullable="false"/>
  <Property Name="Name" Type="Edm.String"/>
  <NavigationProperty Name="Orders" Type="Collection(ODataExample.Model.Order)" ContainsTarget="true"/>
</EntityType>

But If the property is not marked as ContainsTarget, the response contains the data nested at level 4.

If needed I can provide a sample project.

flibustier7seas avatar Jan 31 '18 04:01 flibustier7seas

@flibustier7seas I would appreciate a sample project by you.

bdebaere avatar Jan 31 '18 09:01 bdebaere

@bdebaere https://github.com/flibustier7seas/odata-example

flibustier7seas avatar Feb 01 '18 09:02 flibustier7seas

@flibustier7seas Thank you for the sample. If I replace the code mentioned in your readme to the code below it keeps working. Do you have an idea why?

            builder.EntityType<User>()
                .Expand(10)
                //.Expand(10, nameof(User.Orders))
                // The property will be marked as containment navigation property
                // and expanding anything more than 3 levels the JSON output does not return information
                //.ContainsMany(x => x.Orders)
                ;

bdebaere avatar Feb 02 '18 12:02 bdebaere

@bdebaere In this case you set all properties expandable with maximum depth of expand result of this structural type.

            builder.EntityType<User>()
                .Expand(10)
                //.Expand(10, nameof(User.Orders))
                // The property will be marked as containment navigation property
                // and expanding anything more than 3 levels the JSON output does not return information
                //.ContainsMany(x => x.Orders)
                ;

Wher use Expand(10, nameof(User.Orders)), you set only Orders property expandable with maximum depth of expand result.

flibustier7seas avatar Feb 05 '18 05:02 flibustier7seas

I ran into the same problem. MaxExpansionDepth does not have any effect at all.

The following steps did not fix this:

  • Migrating from .NET Core 3.1 to .NET 5.0
  • Migrating OData-Libraries Microsoft.AspNetCore.OData to 8.0.0-preview3

Whatever value is passed to EnableQueryAttribute, it does not change the behavior:

    [EnableQuery(MaxExpansionDepth = int.MaxValue)]

The method Expand does not exist on EntityTypeConfiguration. https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnet.odata.builder.entitytypeconfiguration?view=odata-aspnetcore-7.0 Not sure if it has been an extension method but if it has been, i am absolutley clueless where it has been moved. But the following did not work on the previous version, that i have been using and on 8.0.0-preview3 i cannot find it:

	var order = builder.EntitySet<Order>(ResourceEnum.Orders.ToString());
	order.EntityType.Expand(10);
	builder.EntityType<OrderPosition>().Expand(10);
	builder.EntityType<OrderDetail>().Expand(10);

The following OData-Query-Options should return expanded Orders that got Positions with Details with an Item and a Store on the Detail but Item and Store are not returned. root/Orders?$top=10&$expand=Position($expand=Detail($expand=Item,Store))&$orderby=Id desc

{
            "Id": 1407,
            "No": 795250,
            "OrderDate": "2020-11-03T00:00:00+01:00",
            "SupplierId": 4103,
            "Position": [
                {
                    "Id": 11469,
                    "PositionNo": 1,
                    "ArticleId": 132967,
                    "DeliveryDateFrom": "2020-11-04T00:00:00+01:00",
                    "DeliveryDateTo": "2020-11-04T00:00:00+01:00",
                    "CustomerId": 5224,
                    "OrderId": 1407,
                    "Detail": [
                        {
                            "Id": 46411,
                            "Quantity": 1.00,
                            "DeliveredQuantity": 1.00,
                            "PP": 22.00000,
                            "ListPP": 22.00000,
                            "DiscountPP": 0.00000,
                            "SP": 39.00000,
                            "OfferPrice": 39.00,
                            "ItemId": 262191,
                            "OrderPositionId": 11469,
                            "StoreId": 4
                        }
                    ]
                }
            ]
        }

JanKotschenreuther avatar Feb 05 '21 12:02 JanKotschenreuther

Has anyone found a solution to this ?

jguerrero09 avatar Aug 07 '24 00:08 jguerrero09