OData / AspNetCoreOData

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

Incorrect Handling of DELETE Request with $each path segment #1108

Open Supernectar opened 9 months ago

Supernectar commented 9 months ago

Assemblies affected ASP.NET Core OData 8.2.3

Describe the bug When attempting to make a DELETE request to delete members of a collection using the $each segment in an OData controller, the expected 200 OK response is not received. Instead, a 404 Not Found response is returned.

Reproduce steps

  1. Clone this repo https://github.com/Supernectar/ODataEachPathSegmentBug and run the project
  2. Send a DELETE request to the endpoint: https://localhost:7234/Customers/$filter(Id gt 4)/$each
  3. Expected: Receive a 200 OK response.
  4. Actual: Receive a 404 Not Found response.

Data Model

public class Customer
{
    public int? Id { get; set; }
    public string? Name { get; set; }
}

EDM (CSDL) Model

<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
    <edmx:DataServices>
        <Schema Namespace="WebApplication1" xmlns="http://docs.oasis-open.org/odata/ns/edm">
            <EntityType Name="Customer">
                <Key>
                    <PropertyRef Name="Id" />
                </Key>
                <Property Name="Id" Type="Edm.Int32" Nullable="false" />
                <Property Name="Name" Type="Edm.String" />
            </EntityType>
        </Schema>
        <Schema Namespace="Default" xmlns="http://docs.oasis-open.org/odata/ns/edm">
            <EntityContainer Name="Container">
                <EntitySet Name="Customers" EntityType="WebApplication1.Customer" />
            </EntityContainer>
        </Schema>
    </edmx:DataServices>
</edmx:Edmx>

Request/Response Request Uri https://localhost:7234/Customers/$filter(Id gt 4)/$each Response Body 404 Not found

Expected behavior According to the OData specification, a DELETE request with the $each segment should return a 200 OK response, with a delta response containing a representation of a deleted entity for each deleted member.

julealgon commented 9 months ago

I've never heard of $each before this post. Is this supported in ASPNETCore ODATA at all?

Supernectar commented 9 months ago

@julealgon The OData documentation explicitly mentions support for the $each segment when making DELETE requests to delete members of a collection (ref: OData Specification). However, from what I could test, this feature is not functioning as expected.

julealgon commented 9 months ago

@Supernectar just keep in mind that the OData spec and the .NET OData implementation are not the same thing. The .NET implementation doesn't support everything that exists in the spec, which is why I questioned whether this was supported in the first place as I'd never heard of it from MSDN documentation.

I'd love to see this working myself though, just to make it clear.

gathogojr commented 9 months ago

Thank you @Supernectar for reporting the issue. We currently don't support $each in ASP.NET Core OData library

xuzhg commented 9 months ago

@julealgon $filter segment and $each are enabled in the ODL library, but they are not supported in the current ASP.NET Core OData.

@Supernectar Since it's not supported, if you want to enable it, you can customize it. Below is a diff based on your github repo, you can apply it to your repo to try: 0001-enable-the-filter-working.patch

Based on the implementation, if we send request as: DELETE https://localhost:7234/Customers/$filter(Id gt 4)/$each

In the debug model, we can get:

image

I'd like to hear from you and @julealgon about how to better implement this in the package directly? And How do you use the $filter segment in the Delete action?

julealgon commented 9 months ago

And How do you use the $filter segment in the Delete action?

In an ideal world, this would leverage this functionality from EFCore @xuzhg:

I'm aware this is somewhat new in EFCore and that OData has not supported it for anything else yet, but it would be absolutely ideal for something like this.