PUT operation leaves derived type properties unchanged when not included in payload
Assemblies affected ASP.NET Core OData 9.3.0
Describe the bug When performing a PUT operation on an entity with a derived type, properties specific to the derived type that are not included in the request payload are not reset to their default values. Instead, they retain their previous values if the entity instance is more derived than the Delta<T> type. It is unclear if this is by design or an implementation oversight, as the OData specification (v4.01 Section 11.4.3) states that omitted properties should be set to their default values, but does not explicitly call out behavior for properties present only on a more derived type than the tracked Delta<T>.
Reproduce steps
- Define a base class and a derived class with additional properties.
- Create an entity of the derived class and persist it with non-default values for derived properties.
- Send a PUT request targeting the base type or a less-derived Delta<T> that omits the derived properties from the payload.
- Observe that the derived properties are not reset.
Data Model
Expected behavior All omitted properties, including those specific to the derived type, should be reset to their default values as per OData PUT semantics.
Screenshots
Additional Context
Additional context It appears that omitted properties in the derived type are not present in the Delta's updateChangedProperty and updateUnchangeProperty sets, so they are neither reset during PUT. Is this behavior intentional or a bug?
Hi @Justinlcx. Thank you for reporting the issue. For PUT semantics, you're expected to have use T rather than Delta<T> on the controller action as illustrated here - https://learn.microsoft.com/en-us/odata/webapi-8/fundamentals/entity-routing?tabs=net60%2Cvisual-studio#updating-a-single-derived-entity
Delta<T> applies to PATCH semantics. In which case, only the properties included in the payload are updated - https://learn.microsoft.com/en-us/odata/webapi-8/fundamentals/entity-routing?tabs=net60%2Cvisual-studio#patching-a-single-derived-entity
Hi @gathogojr, Thank you for the answer. If this is the intended design, could you clarify the purpose of having both the isPut extension and the Put function in Delta<T>? It seems like it's intended to be functional, but it doesn't work properly with derived types.
In DeltaOfT.cs
/// <summary>
/// Overwrites the <paramref name="original"/> entity with the values stored in this Delta.
/// <remarks>The semantics of this operation are equivalent to a HTTP PUT operation, hence the name.</remarks>
/// </summary>
/// <param name="original">The entity to be updated.</param>
public void Put(T original)
{
CopyChangedValues(original);
CopyUnchangedValues(original);
}
Is there any news ?