I’ve recently started interacting with the Epicor REST API (10.2.100) and am confused about what appears to be a datatype discrepancy between the OData Metadata and the PATCH method for two fields in the SalesRepRow model within SalesRepSvc. I’m probably misunderstanding something but thought I’d ask here to find out.
In {{Host}}/api/help/odata/Erp.BO.SalesRepSvc/index#!/OData/getMetadata the fields in question are defined as follows:
However when I execute the PATCH method against {{Host}}/api/v1/Erp.Bo.SalesRepSvc/SalesReps(‘Denmar’,‘TEST’) using Postman and a JSON body containing a SalesRepRow object with those datatypes, the API responds with “400 Bad Request”
This is the error returned by PATCH when using a decimal CommissionPercent:
patch : Cannot convert a primitive value to the expected type ‘Edm.Decimal’. See the inner exception for more details.
This is the error returned by PATCH when using an integer SysRevID:
patch : Cannot convert a primitive value to the expected type ‘Edm.Int64’. See the inner exception for more details.
When testing this in Postman, if I ignore the OData metadata and instead submit the problematic fields as strings, the PATCH is successful.
The reason this is creating a problem for me is because I’m generating C# client classes from the OData metadata using NSwag.CodeGeneration.CSharp, but if this is indeed a datatype discrepancy I’ll need to manually change the datatypes for the affected model fields within the generated client classes.
Is this a known issue, or am I misunderstanding the relationship between the REST methods and the OData metadata?
I thought I should follow-up with details about how I worked around this. I went down a rabbit hole studying the OData JSON specifications and learned that OData 3 (the version Epicor 10.2.100 is using) seemingly doesn’t have a provision for what is referred to as “IEEE 754 Compatibility” which specifies that Edm.Int64 and Edm.Decimal properties are to be serialized as strings. This support was added in OData 4. Here is the related excerpt from the OData V4.0 JSON specification at http://docs.oasis-open.org/odata/odata-json-format/v4.0/os/odata-json-format-v4.0-os.html:
The IEEE754Compatible=true format parameter indicates that the service MUST serialize Edm.Int64 and Edm.Decimal numbers (including the odata.count, if requested) as strings. If not specified, or specified as IEEE754Compatible=false, all numbers MUST be serialized as JSON numbers.
This enables support for JavaScript numbers that are defined to be 64-bit binary format IEEE 754 values [ECMAScript] (see section 4.3.1.9) resulting in integers losing precision past 15 digits, and decimals losing precision due to the conversion from base 10 to base 2.
OData JSON payloads that format Edm.Int64 and Edm.Decimal values as strings MUST specify this format parameter in the media type returned in the Content-Type header.
At that point I decided to make the class generator replace the generated class text with a patch for these properties (nullable doubles and nullable longs) when necessary.