Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default ODataEnumSerializer and ODataEnumDeserializer Fails to Convert Multi-Value Flag Enum to Lower Camel Case #1359

Open
WanjohiSammy opened this issue Nov 25, 2024 · 0 comments · May be fixed by #1367
Assignees
Labels
bug Something isn't working feature P2

Comments

@WanjohiSammy
Copy link
Contributor

WanjohiSammy commented Nov 25, 2024

Assemblies affected
8.x

Describe the bug
The ODataEnumSerializer and ODataEnumDeserializer fails to convert multi-value Flag enums to LowerCamelCase as specified in EnumMember attribute. However, this works with single-value Flag enums.

Example:

Consider the following Flag enum:

[Flags]
[DataContract(Name = "exampleEnum")]
public enum ExampleEnum
{
    [EnumMember(Value = "firstValue")]
    FirstValue = 1,

    [EnumMember(Value = "secondValue")]
    SecondValue = 2,

    [EnumMember(Value = "thirdValue")]
    ThirdValue = 4
}

With the default ODataEnumSerializer, a single-value Flag enum like ExampleEnum.FirstValue is correctly converted to ("firstValue"). However, a multi-value Flag enum like ExampleEnum.FirstValue | ExampleEnum.SecondValue is not converted to ("firstValue, secondValue") as expected. Instead, it remains in its original form as "FirstValue, SecondValue"

Reproduce steps

  1. Clone the repo

    git clone https://github.com/WanjohiSammy/ODataWebApiApplicationSample.git
  2. Build and run the application

  3. Find the ODataWebApiApplication15.http and execute the following requests:

    • GET /odata/Customers:
      Note that the customerType for customer id=1 is "regular" but the customerType for customer id=2 is "Premium, VIP" instead of "premium, vip" in lower camel case
      {
        "@odata.context": "https://localhost:7085/odata/$metadata#Customers",
        "value": [
          {
            "id": 1,
            "name": "Customer1",
            "customerType": "regular"
          },
          {
            "id": 2,
            "name": "Customer2",
            "customerType": "Premium, VIP"
          },
          ...
        ]
      }
    • POST /odata/Customers

      • With "customerType": "Regular, Premium" - a new record is created successfully

      • With lower camel case "customerType": "regular, premium" - request is null

          {
             "Id": 0,
             "Name": "John Doe",
             "CustomerType": "regular, premium"
          }
      • With lower camel case single-value "customerType": "regular" - works as expected

        {
           "id": 0,
           "name": "John Doe",
           "customerType": "regular"
        }
    • PATCH /odata/Customers(2)

      • With "customerType": "Regular, VIP" - the record is updated successfully
      • With lower camel case "customerType": "regular, premium" - delta is null
        {
           "CustomerType": "regular, premium"
        }
      • With lower camel case single-value "customerType": "regular" - works as expected
        {
           "customerType": "vip"
        }

Data Model

EDM (CSDL) Model

<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">
	<edmx:DataServices>
		<Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="NS">
			<EntityType Name="customer">
				<Key>
					<PropertyRef Name="id" />
				</Key>
				<Property Name="id" Type="Edm.Int32" Nullable="false" />
				<Property Name="name" Type="Edm.String" />
				<Property Name="customerType" Type="NS.customerType" />
				<NavigationProperty Name="orders" Type="Collection(NS.Order)" />
			</EntityType>
			<EntityType Name="Order">
				<Key>
					<PropertyRef Name="Id" />
				</Key>
				<Property Name="Id" Type="Edm.Int32" Nullable="false" />
				<Property Name="Amount" Type="Edm.Decimal" Nullable="false" Scale="Variable" />
			</EntityType>
			<EnumType Name="customerType" IsFlags="true">
				<Member Name="regular" Value="1" />
				<Member Name="premium" Value="2" />
				<Member Name="vip" Value="4" />
			</EnumType>
			<Function Name="GetCustomerOrdersTotalAmount" IsBound="true">
				<Parameter Name="bindingParameter" Type="NS.customer" />
				<ReturnType Type="Edm.Int32" Nullable="false" />
			</Function>
			<Function Name="GetCustomerByName" IsBound="true">
				<Parameter Name="bindingParameter" Type="Collection(NS.customer)" />
				<Parameter Name="name" Type="Edm.String" />
				<ReturnType Type="NS.customer" />
			</Function>
			<EntityContainer Name="Container">
				<EntitySet Name="Customers" EntityType="NS.customer">
					<NavigationPropertyBinding Path="orders" Target="Orders" />
				</EntitySet>
				<EntitySet Name="Orders" EntityType="NS.Order" />
			</EntityContainer>
		</Schema>
	</edmx:DataServices>
</edmx:Edmx>

Request/Response

###
GET {{HostAddress}}/odata/Customers
Accept: application/json

###
POST {{HostAddress}}/odata/Customers
Content-Type: application/json

{
   "id": 0,
   "name": "John Doe",
   "customerType": "regular"
}

###
PATCH {{HostAddress}}/odata/Customers(2)
Content-Type: application/json

{
  "customerType": "vip"
}

Expected behavior
Expected lower camel case for multi-value Flag enum to work the same way as for single-value. For example, firstValue, secondValue should work the same way firstValue.

@WanjohiSammy WanjohiSammy added the bug Something isn't working label Nov 25, 2024
@WanjohiSammy WanjohiSammy self-assigned this Nov 26, 2024
@WanjohiSammy WanjohiSammy changed the title Default ODataEnumSerializer Fails to Convert Multi-Value Flag Enum to Lower Camel Case Default ODataEnumSerializer and ODataEnumDeserializer Fails to Convert Multi-Value Flag Enum to Lower Camel Case Dec 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working feature P2
Projects
None yet
1 participant