Skip to Content
Author's profile photo Kenichi Unnai

Introduction: OData $batch Processing with Content ID in SAP Gateway


Dear all,

Thanks for your attention. If you are the one of frequent SCN readers, you would think I’m publishing yet another H2G blog 🙂 – yes this is important topic hence I wrote it.


Do you know OData? – Most likely yes.

Have you ever used OData? Most likely yes too.

And – do you know about “Content ID”? – Perhaps no.

“Content ID” is nothing new, it has been defined in the standard OData specification for a while, based on the idea that any OData app can take advantage of when building relationships between entities. A section of “Batch Processing” (2.2.1. Referencing Requests in a Change Set) describes what it is and how to use it – but without any context, you would have no idea when we use it.

Why we need this?

One very common use case is – OData providers need to support Content ID when we use Header-Items (or “Parent-Children”) data with Offline Store of SMP3/HCPms OData SDK.


Let’s have a quick look at how it works in an offline store. If you’re familiar with Offline Store, it is nothing new. As an OData $batch request, we create a set of  header & item entities in the offline store locally. Each entity has its own create request via OData client API.


Here comes the interesting part. To add related child entities to a parent entity, you need to know, or be able to reference, the parent entity’s ID.  The “Content ID” acts as a reference to the parent entity’s ID. As you see, a Content ID has a prefixed value with a “$” character.


For example, by using the Content ID referencing, you can refer the items with the resource navigation path “$100/ToItems”. $100 indicates the header entity by using Content ID. As it is still created locally, those entities don’t have any finalized key that will be given by the OData services.

Time to flush the local entities. These entities needs to be flushed via OData $batch request.


Once your $batch flush goes successfully, the OData services handle “Content ID” and assign key(s) to the entities for all the set of headers & items on the backend side. Most likely you want to do refresh too.


Got it? As you see, Content ID plays a critical role to handle header-item relationship with Offline Store during OData $batch processing. In other words –  to create child items for entities within a change set of $batch request.

To give you some more practical idea from the OData client SDK perspective, here’s a small piece of code that demonstrates the idea in iOS API (Android, Windows, and Kapsel API follow the same rule):

01 SODataRequestParamBatchDefault *batch = [[SODataRequestParamBatchDefault alloc] init];
02 SODataRequestChangesetDefault *changeset = [[SODataRequestChangesetDefault alloc] init];
04 SODataRequestParamSingleDefault *parentReq = [[SODataRequestParamSingleDefault alloc] initWithMode:SODataRequestModeCreate resourcePath:@"/HeaderSet"];
05 parentReq.payload = parentEntity;
06 parentReq.contentID = @"100";
08 SODataRequestParamSingleDefault *childReq = [[SODataRequestParamSingleDefault alloc] initWithMode:SODataRequestModeCreate resourcePath:@"$100/ToItems"];
09 childReq.payload = childEntity;
11 [changeset.requestParams addObject:parentReq];
12 [changeset.requestParams addObject:childReq];
14 [batch.batchItems addObject:changeset];
16 [store scheduleRequest:batch delegate:self];

#01 & #02:  creating a batch and changeset object.

#04 – #06: is for creating parent entity – as #04 indicates, it is a Header entity. You see the #06 that is assigning Content ID.

#08 – #09: for child entity. #08 indicates the child entityset is described as “$100/ToItems” that is navigation resource path from parent to children.

#11 – #16: execute a $batch request.

That’s all the Content ID referencing from client perspective. Now you get the idea of what Content ID is – and the next question is how to implement OData services that support it.

The aim of the following H2G is how to implement OData $batch processing with Content ID in SAP Gateway.

Note: This introductory page focuses on the Offline Store in SMP3/HCPms OData SDK. However, Content ID Referencing could make sense (or useful) when we have these reasons in general:

  1. You want (or need) to create parent and one or more related child entities in the same transaction.
  2. You choose to use a OData $batch changeset.
  3. You choose to create the relationship by issuing a POST request to the navigation URL of the parent entity (rather than, for example, using a deep insert)
  4. You do not have enough information to construct the edit URL of the parent entity (because some part of the key is generated)

Perhaps another common use case in which we want to use Content ID is when we create a header-items data via HANA Cloud Integration. HCI supports $batch request as a runtime. My buddy colleague Midhun VP wrote a tip of how to execute the $batch call through HCI.



Content ID Referencing is supported in the following versions:

  • SAP Gateway 2.0 SP12+
  • SAP NetWeaver 740 SP13+
  • SAP NetWeaver 750

You have a skillset of building basic CRUD OData services with SAP Gateway Workbench (tx code: SEGW) as explained here: #1 – OData CRUD Crash Course – Getting ready with offline store

Are you ready? Let’s hop in the implementation.



Assigned Tags

      You must be Logged on to comment or reply to a post.
      Author's profile photo Chris Whealy
      Chris Whealy

      Great blog Ken!

      Very well explained

      Author's profile photo Nabi Zamani
      Nabi Zamani

      The best reference to explain Content ID for everyone! Well done!

      Author's profile photo Nabi Zamani
      Nabi Zamani
      Author's profile photo Former Member
      Former Member

      Hi Kenichi,

      We tried implementing batch with content-ID against the offline store. When creating headers, it works fine, but while referencing items ie. ($1/toOrderItems)  it gives an error saying unhandled payload type (for ios) or invalid resource path (for android) . Same payload works perfectly fine for online requests. What must be the reason?

      Unnati Bellare

      Author's profile photo Kenichi Unnai
      Kenichi Unnai
      Blog Post Author

      Were you able to run it successfully with REST client, and the problem only happens via the SDK?

      Author's profile photo Former Member
      Former Member

      Hi Kenichi,
      Sorry for the late response!
      Our Kapsel SDK was outdated, we updated the plugins to 3.15 and it worked perfectly! Thanks!!

      Author's profile photo Andre Julius
      Andre Julius

      Hi Kenichi Unnai


      Thanks for this great blog, I have a doubt in terms of UI5 implementation. I tried as below in UI5, I get an error. on the $1/HeadItemNav section

      oModel.createEntry("/HeadSet", { 
      	"groupId": "foo",
      	properties: aHead
      oModel.createEntry("$1/HeadItemNav", { <-- ERROR HERE: No Metadata for collection /$1/HeadItemNav found
      	"groupId": "foo",
      	properties: aItem
      	"groupId": "foo",
      	success: function(oData){"SUCCESS");
      	error: function(oError){"ERROR");

      Meanwhile if I just use like below, it got through, but I have a difficulty in getting pushing in value for CONTENT_ID_REF.

      oModel.createEntry("/itemSet", { 
      	"groupId": "foo",
      	//"headers":{"Content-ID-Ref":1}, <-- This Does not seem to pass to CONTENT_ID_REF
      	properties: aItem


      1. Is it OK for me just to use "/itemSet" instead of "$1/itemSet" ?
      2. Can you advise how can I push value to IT_OPERATION-INFO-CONTENT_ID_REF?

      Your advice is much appreciated.


      Best Regards


      Andre Julius


      Author's profile photo Jan Nyfeler
      Jan Nyfeler

      Hi Andre

      Have you worked this out? I think it is not possible to add content id Ref as a header field, as content-ID is already in the header, but also sapui5 odata model is not able to createEnry(("/$1....)?