Web core Client - how to load Json from Xdata server direct into WebDBDataset/Grid

Hello comunity,
(my first Post here :grinning:)
how can I load the Json data form a Xdata server into the web dataset?

I build a Xdata server with FDQuery like the video tutorial from Holger Flick.
In his totorial he made a VCL client to load the data with a FDMemorydataset.

I need the same client but in Web core.
I used :
XDataWebClient1.RawInvoke('IGetProcsServiceService.GetProcsbySQL',[],@onResponse);
and
Procedure onResponse(Response:TXDataClientResponse);
...WebDBGrid1.LoadFromJSON(Response.ResultAsObject as TJSObject);
to get the data in "Response". It works but the data are not loaded into the grid.
What is the right way?

LG Christian

Hi
Welcome, I think you cannot directly assign the resulting JSON from FDQuery to TMS web datasets or grids, their formats will not match. FireDac has bunch of metadata in those JSONs in addition to data rows. It works with native FDMemorydataset because they share same format probably.

So I recommend you check this post by @AndrewSimard, to see how he parses that JSON.

1 Like

Hi,
thank you for your quick resonse.
This link to @AndrewSimard was very helpful! It works!
Know I see why the TMS tutuorial use the FireDAC compos on the client side to load the Json content. There is no native way to load the Firedac Json.
And I guess there is also no direct way to load the raw Json with a simple JsonArray like:
[{"Col":"Valiue"}, {...} ]

We must parse the json and add all cols by self.
Imho os here a a open TMS construction site.
".LoadfromJson" seems to be a empty function call.

How ever, my problem is solved - Thanks a lot!

2 Likes

Hello together,
now I have a new problem with my Xdata Server and the Web Core Client, and I hope anybody can help.
I made a update from D11to D11.2 ,TMS Xdata to 5.7.0 and Web Core to 2.0.2.3.

After the update I receive from the "XDataWebConnection" the text
"[object Blob]".
I catch the respone stream direct on the XDataWebconnetion :
procedure TDataModule1.XDataWebConnection1Response(

  • Args: TXDataWebConnectionResponse);*
    Var s:String;
    begin
  • s:=String(Args.Response.Content);*
  • Savestring(s);*
    end;

I expect the firedac format as Json like "{"FDBS":{"Version":16,"Manager":{.....".
Before the the Update it works fine.

The problem seems to be on the Client side. If I Ask the server from the browser, I get the correct stream.

Have any body a idea?
Or is it a Bug?
Or is D11.2 not compatible yet ?

It's a breaking change we introduced in XData 5.7:

  • Improved: TXDataWebClient.RawInvoke now provides a JavaScript Blob object in the Response.Result property, when the server method returns a TStream. (breaking change).

If your XData service returns a TStream, then in Web Core the response will come as TJSBlob type, instead of a string. This is convenient to handle all types of content returned by the method.

Once you have a blob, you can read the string from it. The more straightforward way is to use the text method. Since it's not available directly as a stub in Web Core, you need to use asm for that:

asm
  s = await Args.Response.text();
end;

Thanks for the instant response!
The workaround with the java call doesn't work in my case.

The Call is:

XDataWebClient1.RawInvoke('SQLQueryService.GetData',[params],@onResponse);

and ...

Procedure TFormTest.onResponse(Response:TXDataClientResponse);
var JsText:String;
begin
     asm
       JsText = await Response.Resonse.text();
     end;
   if Response.StatusCode=200 then
     GetQueryData(JsText,XDataWebDataSet1);
end;

With the [ASYNC] directive I get Error:
"undefined:undefined"
Without [ASYNC] and "await" I get:
"ERROR TypeError: Response.text is not a function"
I tried serveral combinations ...
Can you give me an example please?
Thanks.

Is this what you are really using? There is a typo there (Resonse).

Sorry I saw it too late. the missing "p" is just in this post.
I tried several combinations with AYSYNC or without...

JsText = await Response.Response.text();
JsText = await Response.text();

JsText =  Response.Response.text();
JsText =  Response.text();

also with Rawinvoke async..

  Response := await (XDataWebClient1.RawInvokeAsync('SQLQueryService.GetData', [params]) );
     asm
       JsText = (Response.text());
     end;

  Savestring(JsText);

All the same result.

What appears in the browser console when you try to output the content of Response?

console.log(Response.Response)

Screenshot from "Response"
grafik

The Server seem to be Ok. I can get a correkt Json with the Browser...

I'm sorry since you are handling the result of RawInvoke direct, this is what you should use:

JsText = await Response.Result.text();

That was what I tried at first. It makes sence.

In the meantime:
The debugger in Chrome shows for "Response.FResult.text()" a typeerror
1. length: 0
2. name: "text"
3. arguments: (...)
4. caller: [Ausnahme: TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them at Function.invokeGetter (:3:28) at Object.onResponse (http://localhost:8000/....
5. [[Prototype]]: ƒ ()
6. [[Scopes]]: Scopes[0]
May this is the problem?

Okay the direct call works!
It must be used "FResult.text()"

Response := await (XDataWebClient1.RawInvokeAsync('ISQLQueryService.GetData', [params]) );
     asm
       //console.log(Response.FResult);
       JsText =await (Response.FResult.text());
     end;

But:
In my callback function the same code didn't work.

XDataWebClient1.RawInvoke('ISQLQueryService.GetData',[params],@onResponse);
...
...

Procedure TFormTest.onResponse(Response:TXDataClientResponse);
var JsText:String;
begin
     asm
       JsText = await (Response.FResult.text());
     end;

It gives the typeerror
TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them at Function.invokeGetter (:3:28) at Object.onResponse (http://localhost:8000/...

Ok, mixing asm code can be a little bit complicated. You can simplify things by using this approach:

var
  Blob: JSValue;
  JsText: string;
begin
  Blob := Response.Result;
  asm
    JsText = await (Blob.text());
  end;

This solution work's well. Thank you!

1 Like

This topic was automatically closed 60 minutes after the last reply. New replies are no longer allowed.