In this blog, I would like to share how to do business object update operation via Service Layer API.
As Service Layer follows OData protocol, it uses HTTP verb PATCH
or PUT
to update entities. The semantic difference is:
- A
PUT
request indicates a replacement update. All property values with those specified in the request body will be replaced. Missing properties are set to their default values. Be aware of the potential for data-loss in round-tripping properties that the client may not know about in advance. - A
PATCH
indicates a differential update. Those property values that are specified in the request body will be exactly replaced. Missing properties are not altered.PATCH
provides more resiliency between clients and services by directly modifying only those values specified by the client.
Generally, PATCH is strongly recommended while PUT is deprecated.
1. Update a Primitive Property
CardName
is a primitive property of the entity BusinessPartners
. To update the name of the customer "c1", send a PATCH
request as below:
PATCH /BusinessPartners('c1')
{ "CardName": "Updated customer name" }
On success, HTTP code 204 is returned without content.
HTTP/1.1 204 No Content
2. Update a Complex Property
Only those properties of the complex type specified in the payload of the PATCH
request will be modified. For example, AddressExtension
is a complex property of the order entity. The original value of this property is as below:
{
"AddressExtension": {
"ShipToStreet": null,
"ShipToStreetNo": null,
"ShipToBlock": null,
"ShipToBuilding": null,
"ShipToCity": null,
"ShipToZipCode": null,
"ShipToCounty": null,
"ShipToState": null,
"ShipToCountry": null,
"ShipToAddressType": null,
"BillToStreet": null,
"BillToStreetNo": null,
"BillToBlock": null,
"BillToBuilding": "",
"BillToCity": null,
"BillToZipCode": null,
"BillToCounty": null,
"BillToState": null,
"BillToCountry": "US",
"BillToAddressType": null,
"ShipToGlobalLocationNumber": null,
"BillToGlobalLocationNumber": null,
"ShipToAddress2": null,
"ShipToAddress3": null,
"BillToAddress2": null,
"BillToAddress3": null
}
}
Send a PATCH
request with the following payload to update the AddressExtension
:
PATCH /b1s/v1/Orders(9)
{
"AddressExtension": {
"ShipToStreet": "Chenhui",
"ShipToStreetNo": "1001",
"ShipToBuilding": "pvg02",
"ShipToCity": "Shanghai",
"ShipToCounty": "China"
}
}
On success, HTTP code 204 is returned without content.
HTTP/1.1 204 No Content
Then send a HTTP GET request to retrieve the changed AddressExtension
, Service Layer will return:
{ ...
"AddressExtension": {
"ShipToStreet": "Chenhui",
"ShipToStreetNo": "1001",
"ShipToBlock": null,
"ShipToBuilding": "pvg02",
"ShipToCity": "Shanghai",
"ShipToZipCode": null,
"ShipToCounty": "China",
"ShipToState": null,
"ShipToCountry": null,
"ShipToAddressType": null,
"BillToStreet": null,
"BillToStreetNo": null,
"BillToBlock": null,
"BillToBuilding": "",
"BillToCity": null,
"BillToZipCode": null,
"BillToCounty": null,
"BillToState": null,
"BillToCountry": "US",
"BillToAddressType": null,
"ShipToGlobalLocationNumber": null,
"BillToGlobalLocationNumber": null,
"ShipToAddress2": null,
"ShipToAddress3": null,
"BillToAddress2": null,
"BillToAddress3": null
}
}
3. Update a Collection Property
According to the OData standard, since collection members have no individual identity, PATCH
is not supported for collection properties.
However, this rule does not suit the B1 data model well, as the collection members of B1 business objects have individual identity. Considering this fact, Service Layer extends the PATCH
to support collection properties.
[Add and Update elements in Collection]
Before 9.1H PL12, Service Layer allows to add and update the elements in a collection property. Delete element in collection is not supported.
Assume there is an order with DocEntry
= 9 and having one document line as below:
{
...
"DocEntry": 9,
"DocNum": 4,
"CardCode": "bp004",
"DocDate": "2016-04-23",
"DocDueDate": "2016-04-23",
"DocumentLines": [
{
"LineNum": 0,
"ItemCode": "i001",
"UnitPrice": 10,
"Quantitiy": 1
}
]
...
}
To add a new document line and update the UnitPrice
from an existing document line in one round trip, send a request as below:
PATCH /b1s/v1/Orders(9)
{
"DocumentLines": [
{
"LineNum": 0,
"ItemCode": "i001",
"UnitPrice": 20,
"Quantitiy": 1
},
{
"ItemCode": "i002",
"UnitPrice": 10,
"Quantitiy": 2
}
]
}
On success, HTTP code 204 is returned without content.
HTTP/1.1 204 No Content
Then send a HTTP GET request to check the changed line, Service Layer will return:
{
...
"DocumentLines": [
{
"LineNum": 0,
"ItemCode": "i001",
"UnitPrice": 20,
"Quantitiy": 1
},
{
"LineNum": 1,
"ItemCode": "i002",
"UnitPrice": 10,
"Quantitiy": 2
}
]
...
}
[Add, Update and Delete elements in collection]
Since 9.1H PL12, Service Layer provides a way to support removing an element in the collection property by adding a special header in the request:
B1S-ReplaceCollectionsOnPatch
=true
Assume there is one business partner with CardCode
= 'bp004' and having two addresses (e.g. "addr1" and "addr2") as below:
{
...
"BPAddresses": [
{
"AddressName": "addr1",
"Country": "US",
"AddressType": "bo_BillTo",
"BPCode": "bp004",
"RowNum": 0,
....
},
{
"AddressName": "addr2",
"Country": "US",
"AddressType": "bo_BillTo",
"BPCode": "bp004",
"RowNum": 1,
...
}
],
...
}
To add a new address (e.g. "addr3"), update the existing address from "addr2" to "ddr2_new", and remove address "addr1" in one round trip, send a request as below:
PATCH /b1s/v1/BusinessPartners('bp004')
B1S-ReplaceCollectionsOnPatch=true
{
"BPAddresses": [
{
"AddressName": "addr2_new",
"AddressType": "bo_BillTo",
"BPCode": "bp004",
"RowNum": 1
},
{
"AddressName": "addr3",
"AddressType": "bo_BillTo",
"BPCode": "bp004"
}
]
}
On success, HTTP code 204 is returned without content.
HTTP/1.1 204 No Content
Then send a HTTP GET request to check the addresses, Service Layer will return
{
...
"BPAddresses": [
{
"AddressName": "addr2_new",
"Country": "US",
"AddressType": "bo_BillTo",
"BPCode": "bp004",
"RowNum": 1,
...
},
{
"AddressName": "addr3",
"Country": "US",
"AddressType": "bo_BillTo",
"BPCode": "bp004",
"RowNum": 2,
...
}
],
...
}
[Note]
- Read only properties (e.g.
CardCode
) are not possible to be updated. They are ignored silently if assigned in the request. - (Version Note: since 9.1 patch 02) The HTTP verb
MERGE
is also supported and behavior likePATCH
. It's not recommended to use as it's not a standard HTTP verb. It's just for compatibility like supporting Microsoft WCF framework.
In sum, Service Layer mainly uses the OData PATCH verb to updatethe B1 business objects . Actually, Service Layer also supports PUT. As PUT does not conform to the update semantics defined in B1 data model, it is not suggested to use.