TWebCore and XDATA

when I call the funtion (http://localhost:8000/tms/xdata/Data_xChangeService/Get_Abteilung) in the browser, taht is the result:
// 20191105151638
// http://localhost:8000/tms/xdata/Data_xChangeService/Get_Abteilung

{
  "FDBS": {
    "Version": 15,
    "Manager": {
      "UpdatesRegistry": true,
      "TableList": [
        {
          "class": "Table",
          "Name": "Query_Main",
          "SourceName": "abteilung",
          "SourceID": 1,
          "TabID": 0,
          "EnforceConstraints": false,
          "MinimumCapacity": 50,
          "ColumnList": [
            {
              "class": "Column",
              "Name": "AbteilungsID",
              "SourceName": "AbteilungsID",
              "SourceID": 1,
              "DataType": "UInt32",
              "Precision": 10,
              "Searchable": true,
              "AllowNull": true,
              "AutoInc": true,
              "Base": true,
              "AutoIncrementSeed": -1,
              "AutoIncrementStep": -1,
              "OAllowNull": true,
              "OInWhere": true,
              "OInKey": true,
              "OAfterInsChanged": true,
              "OriginTabName": "nedcom2.abteilung",
              "OriginColName": "AbteilungsID",
              "SourcePrecision": 10
            },
            {
              "class": "Column",
              "Name": "Abteilung",
              "SourceName": "Abteilung",
              "SourceID": 2,
              "DataType": "AnsiString",
              "Size": 45,
              "Searchable": true,
              "AllowNull": true,
              "Default": true,
              "Base": true,
              "OAllowNull": true,
              "OInUpdate": true,
              "OInWhere": true,
              "OAfterInsChanged": true,
              "OriginTabName": "nedcom2.abteilung",
              "OriginColName": "Abteilung",
              "SourceSize": 45
            },
            {
              "class": "Column",
              "Name": "Test",
              "SourceName": "Test",
              "SourceID": 3,
              "DataType": "AnsiString",
              "Size": 45,
              "Searchable": true,
              "AllowNull": true,
              "Default": true,
              "Base": true,
              "OAllowNull": true,
              "OInUpdate": true,
              "OInWhere": true,
              "OAfterInsChanged": true,
              "OriginTabName": "nedcom2.abteilung",
              "OriginColName": "Test",
              "SourceSize": 45
            }
          ],
          "ConstraintList": [
            
          ],
          "ViewList": [
            
          ],
          "RowList": [
            {
              "RowID": 0,
              "Original": {
                "AbteilungsID": 10,
                "Abteilung": "Verkauf",
                "Test": "0"
              }
            },
            {
              "RowID": 1,
              "Original": {
                "AbteilungsID": 20,
                "Abteilung": "Anwendung & Entwicklung",
                "Test": "0"
              }
            },
            {
              "RowID": 2,
              "Original": {
                "AbteilungsID": 30,
                "Abteilung": "Technische Büro",
                "Test": "0"
              }
            },
            {
              "RowID": 3,
              "Original": {
                "AbteilungsID": 40,
                "Abteilung": "Arbeitsvorbereitung",
                "Test": "0"
              }
            },
            {
              "RowID": 4,
              "Original": {
                "AbteilungsID": 50,
                "Abteilung": "Produktion",
                "Test": "0"
              }
            },
            {
              "RowID": 5,
              "Original": {
                "AbteilungsID": 60,
                "Abteilung": "Werkzeugbau",
                "Test": "0"
              }
            },
            {
              "RowID": 6,
              "Original": {
                "AbteilungsID": 70,
                "Abteilung": "Einkauf",
                "Test": "0"
              }
            },
            {
              "RowID": 7,
              "Original": {
                "AbteilungsID": 80,
                "Abteilung": "Qualitätssicherung",
                "Test": "0"
              }
            },
            {
              "RowID": 8,
              "Original": {
                "AbteilungsID": 90,
                "Abteilung": "EDV",
                "Test": "0"
              }
            },
            {
              "RowID": 9,
              "Original": {
                "AbteilungsID": 100,
                "Abteilung": "Finanzbuchhaltung",
                "Test": "0"
              }
            },
            {
              "RowID": 10,
              "Original": {
                "AbteilungsID": 110,
                "Abteilung": "Geschäftsführung",
                "Test": "0"
              }
            },
            {
              "RowID": 11,
              "Original": {
                "AbteilungsID": 111,
                "Abteilung": "PM",
                "Test": "0"
              }
            }
          ]
        }
      ],
      "RelationList": [
        
      ]
    }
  }
}
Queued at 0
Started at 0.96 ms
Resource Scheduling DURATION
Queueing
0.96 ms
Connection Start DURATION
Stalled
0.57 ms
Request/Response DURATION
Request sent
69 μs
Waiting (TTFB)
1.91 ms
Content Download
0.47 ms
Explanation 3.97 ms

Is that helpful for you?

1. The server response is configured as a TStream. Thus, the result will always come, in web core, as a string. This is what you need to correctly parse the result:


      JFDBS := TJSObject(TJSObject(TJSJson.Parse(string(Response.Result)))['FDBS']);
      JManager := TJSObject(JFDBS['Manager']);
      JTableList := TJSObject(TJSArray(JManager['TableList'])[0]);
      JRowList := TJSArray(JTableList['RowList']);
      console.log(JRowList);


2. In your JSON result, TableList is an array, not an object. Thus you need to get the first item of an array (I’m not sure what you should do if you have two items in the array, but that is specific to your application):


      JFDBS := TJSObject(TJSObject(TJSJson.Parse(string(Response.Result)))['FDBS']);
      JManager := TJSObject(JFDBS['Manager']);
      JTableList := TJSObject(TJSArray(JManager['TableList'])[0]);
      JRowList := TJSArray(JTableList['RowList']);
      console.log(JRowList);


3. Since in your JSON result the actual data come in a subject (Original):


                "RowList": [{
                    "RowID": 0,
                    "Original": {
                        "AbteilungsID": 10,
                        "Abteilung": "Verkauf",
                        "Test": "0"
                    }
                }, 


You need to create your dataset fields with field name prefixed with "Original.", e.g.:

Original.AbteilungsID
Original.Abteilung
Original.Test

I implemented all procedures you discuss and my fiinal code on client application is below. But i have a error 'entitysetname not set ' . What i'm wrong ?
In Response.ResponseText there is a JSON string with all data...

procedure TfrmPrestMac.btPrestClick(Sender: TObject);

procedure OnResponse(Response: TXDataClientResponse);
Var JFDBS: TJSObject; JManager: TJSObject; JTableList: TJSObject; JRowList: TJSArray;
begin
JFDBS := TJSObject(TJSObject(TJSJson.Parse(string(Response.Result)))['FDBS']);
JManager := TJSObject(JFDBS['Manager']);
JTableList := TJSObject(TJSArray(JManager['TableList'])[0]);
JRowList := TJSArray(JTableList['RowList']);

showmessage(Response.ResponseText);

//showmessage(js.ToString(JRowList));

wdPrest.Close();
//wdPrest.entitysetname:=js.ToString(JTableList);
wdPrest.SetJsonData(JRowList);
wdPrest.Open();

end;
begin
wdcPrest.RawInvoke(
'IMyQueryService.DoQuery',['',
'SELECT Azione, Data_Ora, TDS_Reg, Info_Cli FROM SMS_Act WHERE TDS_Reg > 200'],
@OnResponse);
end;

I created persistent fields and now go ... BUT now grid show me the rows of the records but they are Empty !! there is a wrong type data ?

Yes, you need to create persistent fields manually if you don't set EntitySetName.
As for grid being empty, inspect the request result and the objects if your code in OnResponse tries to read one single property wrongly, the result would be null. Make sure you are reading the returned JSON structure correctly.

persistent fields manually
by code ex. I need to put Original before ?

wdPrest.Close();
wdPrest.FieldDefs.Clear;
wdPrest.FieldDefs.Add('Original.Azione',ftString,5);
wdPrest.FieldDefs.Add('Original.Data_Ora',ftString,20);
wdPrest.FieldDefs.Add('Original.TDS_Reg',ftString,10);
wdPrest.FieldDefs.Add('Original.Info_Cli',ftString,200);
wdPrest.SetJsonData(JRowList);
wdPrest.Open();

But if i create field by code give me EntitySetName .dont set ...

if i create at design time fields dont give me error of EntitySetName but all records in grid are empty. I must put original in it ? where ? give me a cant find field ...

You should create the fields at design-time, at least to understand what's going on.
I can't tell why your grid is empty, your code looks correct according to the grid. Then I could only give you more information if I have more information, preferable a small sample project that reproduces the issue.

I'd like to add another voice to Guido's post...

If I have an XDataWebDataset dropped on a form, and then create fields at design time, and then try to populate it with the SetJsonData function, it works.

If I instead create the fields for the same control using FieldDefs at runtime, it seems to think it still needs the EntitySetName set and thus fails.

I think what he's trying to do (and what I'm trying to do) is to have a local TDataset that contains the records coming from something like an FDQuery on the server, without using the Entity mechanism but rather a service call. And as we can't use a local TFDMemTable (for reasons that are not clear to me), the XDataWebDataset seems the closest thing, particularly with the SetJsonData function beign availabe. But for this to work we need to be able to define the fields at runtime and do everything else without actually using the connectivity aspects of the XDataWebDataset in this instance as we're supplying the data after having gotten it (manually) via Json previously.

If there is a dummy field added at runtime then the error is different (can't find matching fields) so presumably there's a problem in XDataWebDataset's handling of FieldDefs. Maybe they're just not iimplemented?

Perhaps I can writeup an issue that more clearly shows the process from having an FDQuery dump data into a TStream on an XData endpoint and then having it recreated locally so it can be used in a local WebDBGrid or available in the usual TDataSet First/Next kind of mechanism. With the TStream and its JSON contents being used as a simple communications mechanism without having to pay much attention to how it works.

There is no "memory dataset" in Web Core because there is no direct memory access in JavaScript. It doesn't make sense.

TXDataWebDataset is indeed the correct "memory dataset" you can get in Web Core, because it supports JavaScript objects and primitive values, which is the closes you can get as "memory".

All you need to do is input raw data using SetJsonData, as you do. But of course you have to have your fields defined in advance, to tell the dataset which data from the objects you want to be treated as dataset field. Yes, I think more detail about what you are trying to achieve would be needed.