Incorrect Handling of DELETE Request with $each path segment
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
- Clone this repo https://github.com/Supernectar/ODataEachPathSegmentBug and run the project
- Send a DELETE request to the endpoint: https://localhost:7234/Customers/$filter(Id gt 4)/$each
- Expected: Receive a 200 OK response.
- 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.
I've never heard of $each before this post. Is this supported in ASPNETCore ODATA at all?
@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.
@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.
Thank you @Supernectar for reporting the issue. We currently don't support $each in ASP.NET Core OData library
@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:
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?
And How do you use the $filter segment in the Delete action?
In an ideal world, this would leverage this functionality from EFCore @xuzhg:
- https://learn.microsoft.com/en-us/ef/core/saving/execute-insert-update-delete#executedelete
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.