SAPUI5 Create OData entity with dates - generates

2019-08-21 11:24发布

问题:

We are trying to create an entity that has date attributes via an odata service. Backend is an sap system. This entity has only 3 key attributes plus a bunch of other attributes. We have identified that dates in the keys are the root cause of the problem.

Keys:

  • Pernr type string,
  • begda type datetime
  • endda type datetime.

The code below, (which does not work), has been severely simplified when trying to troubleshoot the issue. At the moment, it reads an entity from an entity set and immediately tries to create one with exactly the same data.

Code:

var oODataModel = new sap.ui.model.odata.ODataModel("/sap/opu/odata/sap/Z_PERSONAL_DATA_SRV/");

//Test entity to be saved
var entity = null;

//Handler for read error
var handleReadE = function (oEvent){ 
    alert("error");
};

//Handler for read success
var handleRead = function (oEvent){
    //Get the data read from backend
    entity = oEvent.results[0];

    //Try to create a new entity with same data
    oODataModel.create('/PersDataSet', entity, null, function(){
        alert("Create successful");
    },function(oError){
        alert("Create failed", oError);
    });
};

oODataModel.read("/PersDataSet", null, [], true, handleRead, handleReadE);

In the gateway error log, an xml parsing error appears. In this log, we can see the request data and it can be seen that the dates are transported with String types. These dates are defined in the service as DateTimes so the request is rejected. Example:

<m:properties>
<d:Pernr m:type="Edm.String">00000001</d:Pernr>
    <d:Endda m:type="Edm.String">9999-12-31T00:00:00</d:Endda>
    <d:Begda m:type="Edm.String">1979-05-23T00:00:00</d:Begda>

When the entity is read, the backend does not send any type information. It sends like the following example:

<m:properties>
   <d:Pernr>72010459</d:Pernr>
   <d:Endda>9999-12-31T00:00:00</d:Endda>
   <d:Begda>1876-07-21T00:00:00</d:Begda>

And, indeed, if we try to save the same info without the type=".." it works. So the problem are the incorrect types ODataModel.create adds to the xml.

My question is: Can I tell ODataModel.create to not add this type info? It is not doing a good job inferring the types.

Can anyone share an example reading and writing dates through odata?

Thank you very much in advance.

回答1:

the data returned from oODataModel.read is raw, before you post you need to parse it

 var handleRead = function (oEvent){
   //Get the data read from backend
   entity = oEvent.results[0];

   var newEntity = jQuery.extend({},entity);
   delete newEntity.__metadata;
   newEntity.Begda = new Date(entity.Begda);
   newEntity.Endda = new Date(entity.Endda);

   //Try to create a new entity with same data
   oODataModel.create('/PersDataSet', newEntity, null, function(){

why not use json instead of xml?



回答2:

Thanks all for the help. We got this working accounting for the following:

The problem of the wrong types appended to the attributes comes from the read itself. The object returned by read has a __metadata attribute which describes the values. In this object the dates are set with type=edm.string, even when the service says they are DateTime. To me this is a bug of the .read function.

When trying to use the same object to save, create sees the __metatada on the entry and uses those values, producing type edm.string type for the dates. This caused the request to be rejected. Manually changing these __metadata.properties...type to Edm.DateTime makes it work.

In the end, we did the following:

  • Dates are parsed manually from the Odata response, creating a js Date object from the strings in format "yyyy-mm-ddT00:00:00", to make it work with control bindings. When we want to save, the reverse is done.
  • The object to be created is a new object with only the attributes we care (no __metadata)