HTML, CSS, JavaScript
New User to Web Tools - Basic Use Problem
Gravatar is a globally recognized avatar based on your email address. New User to Web Tools - Basic Use Problem
  Gregg B
  All
  Dec 10, 2022 @ 06:51am

I'm just learning to use Web Tools - want to be able to connect to REST APIs. The first thing I tried is a very basic example that was found in the "samples" provided in the help docs. Each time running it (and other code as well) an error that says “Variable ‘WWWVERSION_NUMBER’ is not found”.

Here is the code:

SET PATH TO "F:\Westwind\wwClient-7.29.0\classes" ADDITIVE
SET EXACT OFF
do wwHttp
loProxy = CREATEOBJECT("wwJsonServiceClient")

lcUrl = "https://albumviewer.west-wind.com/api/artists"
loArtists = loProxy.CallService(lcUrl)

IF (loProxy.lError OR ISNULL(loArtists))
   ? loProxy.cErrorMsg
   RETURN
ENDIF   

*** Service returns an array which is turned into a FoxPro collection
? loArtists.Count  && Collection 
FOR EACH loArtist in loArtists
   ? loArtist.ArtistName
   ? loArtist.Description
   ? loArtist.ImageUrl
   ? "---"
ENDFOR

I think its something to do with missing files or dependencies not being set up properly but all the files seem to be available.

thanks.

Gravatar is a globally recognized avatar based on your email address. re: New User to Web Tools - Basic Use Problem
  Tore Bleken
  Gregg B
  Dec 10, 2022 @ 07:05am

You must make sure that the file wconnect.h is in your path.

Gravatar is a globally recognized avatar based on your email address. re: New User to Web Tools - Basic Use Problem
  Gregg B
  Tore Bleken
  Dec 10, 2022 @ 10:07am

Thanks. I thought of that, and the file is in the same directory as the program I am trying and also in the "classes" subdirectory, which I reference with the PATH statement.

Do I need to reference wconnect.h somewhere in the code?

Gravatar is a globally recognized avatar based on your email address. re: New User to Web Tools - Basic Use Problem
  Gregg B
  Gregg B
  Dec 10, 2022 @ 10:39am

I just got it working by compiling wwhttp.prg. Ran it again and it worked!

Thanks for your help. I appreciate it.

Gravatar is a globally recognized avatar based on your email address. re: New User to Web Tools - Basic Use Problem
  Rick Strahl
  Gregg B
  Dec 10, 2022 @ 11:02am

You need to add the path to wconnect.h which is not in the classes folder but the one above it (or copy the file somewhere where FoxPro can find it).

SET PATH TO "F:\Westwind\wwClient-7.29.0" ADDITIVE
SET PATH TO "F:\Westwind\wwClient-7.29.0\classes" ADDITIVE

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: New User to Web Tools - Basic Use Problem
  Gregg B
  Rick Strahl
  Dec 11, 2022 @ 06:18am

The main reason I purchased the tools was to be able to connect to the Monday.com API, among others. After multiple hours of 'trial and error, I was able to connect and make a post successfully, but it says that the body of the post is malformed. Monday.com actually uses 'GraphQL', as explained in this link. When I post the body into their 'playground', it works but does not work with my post. After trying to form the body organically with the tools, I decided to post the code verbatim right in the JSON string to see if it would work.

Here is my code:

loProxy = CREATEOBJECT("wwJsonServiceClient")

DO wwJsonSerializer
DO wwDynamic


loCust = CREATEOBJECT("wwDynamic")

lcJson = 'query {boards(limit:1) {id name}}'

? lcJson

*** Create custom Http Object for Authentication
loHttp = CREATEOBJECT("wwHttp")
loHttp.AddHeader("Content-Type","application/json")
loHttp.AddHeader("Authorization","TOKENGOESHERE")

*** Pass it to the proxy to use
loProxy.CreatewwHttp(loHttp)

loCust = loProxy.CallService("https://api.monday.com/v2",lcJson,"POST")

IF  loProxy.lError
   ? loProxy.cErrorMsg
   RETURN
ENDIF


oResult = JsonSerialize(loCust)

? oResult
Gravatar is a globally recognized avatar based on your email address. re: New User to Web Tools - Basic Use Problem
  Rick Strahl
  Gregg B
  Dec 11, 2022 @ 01:41pm

I'm sure there's a question in that message somewhere... 😄

GraphQL isn't JSON but rather it's a raw GraphQL query string. You're trying to convert the raw string to JSON which is going to break the value.

Short answer is you can't use wwJsonService for a GraphQL query, because wwJsonService expects any input to be a JSON value, not a raw string. For this to work you need to use raw wwHTTP and manually deserialize the JSON that comes back.

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: New User to Web Tools - Basic Use Problem
  Gregg B
  Rick Strahl
  Dec 11, 2022 @ 02:32pm

You are right - I did not ask a specific question - my bad. I did say that the body was malformed and assumed you knew I needed to know why. Do you have an example of how to do "raw wwHTTP"? Is there a function within your Web Tools to do that?

Gravatar is a globally recognized avatar based on your email address. re: New User to Web Tools - Basic Use Problem
  Gregg B
  Gregg B
  Dec 12, 2022 @ 07:46am

Rick, sorry to be a pain, but I've spent hours on the 'basic' documents you sent me and I still cannot get it to work. I think their version of GraphQL may be a little different. Seems that in the Javascript example they give, they stringify the body, which tells me it is more than just a raw string of data. My question is this: should I 'serialize' (using your terminology) the body text before sending and if so, how do I indicate that this goes in the 'body' of the string I send to them? Here is a screenshot of their help document:

Thanks again.

Gravatar is a globally recognized avatar based on your email address. re: New User to Web Tools - Basic Use Problem
  Rick Strahl
  Gregg B
  Dec 12, 2022 @ 10:52am

It's a raw string. They are stringifying an object. You're going to provide the raw JSON string.

You can stringify this:

loQuery = CREATEOJBECT("EMPTY")
ADDPROPERTY(loQuery, "query", ['{ boards(limit: 1) { id:name } }'])

loResult = loService.CallMethod(lcUrl, loQuery)

My point is that creating the JSON and then embedding the GraphQL query as a string is often a waste of time, because the query itself is a string not an object. I suppose once you add parameters using an object makes more sense as you can dynamically provide the dynamic values needed to run the query.

or manually:

loQuery = CREATEOJBECT("EMPTY")
ADDPROPERTY(loQuery, "query", ['{ boards(limit: 1) { id:name } }'])
loSer = CREATEOBJECT("wwJsonSerializer")
lcJson = loSer.Serialize(loQuery)

loHttp = CREATEOBJECT("wwHttp")
loHttp.cContentType = "application/json"
lcJsonResult = loHttp.Post(lcUrl, STRCONV(lcJson,9))

Based on what I saw in the documentation why are you using the GraphQL anyway - they have a JSON API that will be easier to use from the FoxPro end.

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: New User to Web Tools - Basic Use Problem
  Gregg B
  Gregg B
  Dec 12, 2022 @ 09:26pm

Thank You, Rick! It's working much better; the only thing it's complaining now about is the double quotation marks. If I take the double quotation marks out of the string and post it into the playground, it loves it! I tried to strip them out with strtran() but then the call didn't work at all. Any ideas on the quotation marks issue? Where did you see there is another API available besides GraphQL? I didn't know I had a choice. Thanks again; your software is awesome. Here is what I have now:

propname='query'
loQuery = CREATEOBJECT("EMPTY")
ADDPROPERTY(loQuery, propname, [boards(limit: 1) { id:name } ])
Gravatar is a globally recognized avatar based on your email address. re: New User to Web Tools - Basic Use Problem
  Rick Strahl
  Gregg B
  Dec 13, 2022 @ 12:14pm

Nah that's just me reading the GraphQL incorrectly. The inner quotes were wrong - that's just the JSON representation of the GQL query string.

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: New User to Web Tools - Basic Use Problem
  Gregg B
  Gregg B
  Dec 13, 2022 @ 01:20pm

Thanks, Rick. As you can see in the code I posted, I already took those inner quotes out. It seems like it adds double quotes on its own for some reason. Any suggestions?

Gravatar is a globally recognized avatar based on your email address. re: New User to Web Tools - Basic Use Problem
  Max Parker
  Gregg B
  Dec 14, 2022 @ 02:10am

interesting information

Gravatar is a globally recognized avatar based on your email address. re: New User to Web Tools - Basic Use Problem
  Rick Strahl
  Gregg B
  Dec 14, 2022 @ 11:50am

Quotes are the string delineator.

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: New User to Web Tools - Basic Use Problem
  Gregg B
  Rick Strahl
  Dec 14, 2022 @ 12:56pm

Here is the code I use:

loSer = CREATEOBJECT("wwJsonSerializer")
lcJson = loSer.Serialize(loQuery)
viewstring=STRTOFILE(lcJson,"f:\westwind\json_string.txt")

Here is what is in the file(json_string.txt) {"query": "boards(limit: 1) { id:name }"}

If I take those quotes out and paste it into the 'playground', it loves it. Posting it using the vfp program produces a parse error.

Is there a way to take the quotes out? Thanks.

Gravatar is a globally recognized avatar based on your email address. re: New User to Web Tools - Basic Use Problem
  Rick Strahl
  Gregg B
  Dec 14, 2022 @ 03:21pm

without the quotes it's not valid JSON.

GraphQL queries - the query string anyway, are strings. you have to format the string appropriately as a string.

See here:

Make GraphQL requests from Curl

Same thing there. The query is a string not an object.

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: New User to Web Tools - Basic Use Problem
  Gregg B
  Rick Strahl
  Dec 20, 2022 @ 07:40am

Sorry to bother you again. I reached out to Monday.com and told them my dilemma about not being able to access their API because my script produces valid JSON. I also asked them if they had a REST API to use instead and here was their response:

No we do not use REST API and our API is based on GraphQL, so you should use the GraphQL format as stated in our documentation.

What needs to be in JSON format is your column values if you are looking to mutate data. The returned data is also in JSON format.

Why are you trying to change your query into JSON? This wouldn't work in any setting as the query needs to follow the GraphQL format as stated in our documentation.

I am really in a tough spot now. I saw on your website that you do consultations in addition to selling software. Can I hire you to help me figure this out?

Gravatar is a globally recognized avatar based on your email address. re: New User to Web Tools - Basic Use Problem
  Rick Strahl
  Gregg B
  Dec 20, 2022 @ 12:04pm

Sure I can take a look. Send me a private email and we can go from there...

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: New User to Web Tools - Basic Use Problem
  Gregg B
  Rick Strahl
  Jan 28, 2023 @ 06:57am

OK, well I scrapped Monday.com because I couldn't connect to their API from Westwind. I invested in a new CSR: KEAP, which has a regular REST API. Its complaining because it is looking for some brackets in the JSON string. Here is what it is expecting (from the help documentation):

--data-raw '{
   "email_addresses":[
      {
         "email":"my_first_api@example.com",
         "field":"EMAIL1",
         "opt_in_reason":"Opt-in reason"
      }
   ]
}' 

Here is what my string looks like: {"email_addresses": {"email": "gbarfield@benebloc.com","field": "EMAIL1","opt_in_reason": "Opt-in reason"}}

If I put those 'brackets' "[" "]" in as their example has, I can paste it into Postman and it works fine.

Here is my VFP code:

SET PATH TO "F:\Westwind\wwClient-7.29.0" ADDITIVE
SET PATH TO "F:\Westwind\wwClient-7.29.0\classes" ADDITIVE
SET EXACT OFF

DO wwHttp
loObject = CREATEOBJECT("EMPTY")

DO wwJsonSerializer
loSer = CREATEOBJECT("wwJsonSerializer")
lcJson = loSer.Serialize(loObject)

loCustomer = CREATEOBJECT("EMPTY")  
ADDPROPERTY(loCustomer, "email_addresses")

*** Add a nested object
loAddress = CREATEOBJECT("EMPTY")  
ADDPROPERTY(loCustomer, "email_addresses", loAddress)  && Add as child to ^customer
ADDPROPERTY(loAddress, "email", "gregg@test.com")
ADDPROPERTY(loAddress, "field", "EMAIL1")
ADDPROPERTY(loAddress, "opt_in_reason", "Opt-in reason")

loSer = CREATEOBJECT("wwJsonSerializer")
lcJson = loSer.Serialize(loCustomer)

STRTOFILE(lcJson,"f:\westwind\jsonfile.txt")

loHttp = CREATEOBJECT("wwHttp")
loHttp.AddHeader("Content-Type","application/json")
loHttp.AddHeader("X-Keap-API-Key","mytokengoeshere")

lcJsonResult = loHttp.Post("https://api.infusionsoft.com/crm/rest/v2/contacts?fields=email_addresses", lcJson)


? lcJsonResult

What I am doing wrong?

Gravatar is a globally recognized avatar based on your email address. re: New User to Web Tools - Basic Use Problem
  Rick Strahl
  Gregg B
  Jan 28, 2023 @ 12:28pm

email_addresses is an array in the JSON. To create that from FoxPro with wwJsonSerializer you need to use a Collection object, then add the item to the collection for the JSON to render the way you have it there.

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: New User to Web Tools - Basic Use Problem
  Gregg B
  Rick Strahl
  Jan 28, 2023 @ 02:56pm

Thank you, Rick. I am making progress. Now I just need to put 'email_addresses' as the name of the collection (outside the brackets). I think I need to add 'child' to loCustomer. Can you show me how to do that to make it come out correctly. I spent a couple of hours trying. Here is my code:

DO wwHttp
loObject = CREATEOBJECT("EMPTY")

DO wwJsonSerializer
loSer = CREATEOBJECT("wwJsonSerializer")
lcJson = loSer.Serialize(loObject)

loCol = CREATEOBJECT("Collection")

loCustomer = CREATEOBJECT("EMPTY")  
ADDPROPERTY(loCustomer,"email_addresses")

loAddress = CREATEOBJECT("EMPTY")  
ADDPROPERTY(loAddress, "email", "gregg@test.com")
ADDPROPERTY(loAddress, "field", "EMAIL1")
ADDPROPERTY(loAddress, "opt_in_reason", "Opt-in reason")
loCol.Add(loAddress)

lcjson = loSer.Serialize(loCol, .T.)

Thank you in advance.

Gravatar is a globally recognized avatar based on your email address. re: New User to Web Tools - Basic Use Problem
  Rick Strahl
  Gregg B
  Jan 28, 2023 @ 05:16pm

You have to match the object structure. Top level is an object that contains the collection:

*** Top level object (no name)
loEntity = CREATEOBJECT("EMPTY")
ADDPROPERTY(loEntity, "email_addresses")

*** Create the email item to add to collection
loEmail = CREATEOBJECT("EMPTY")
ADDPROPERTY(loEmail,"email","blah@blah.com")
* ...

*** Create the collection and add Email
loCol = CREATEOBJECT("Collection")
loCol.Add(loEmail)

*** Set the collection to the object Emails
loEntity.email_addresses = loCol

*** serializer
lcJson = loSer.Serialize(loEntity)
Gravatar is a globally recognized avatar based on your email address. re: New User to Web Tools - Basic Use Problem
  Gregg B
  Rick Strahl
  Jan 28, 2023 @ 07:36pm

It works! You rock. Thanks!

Gravatar is a globally recognized avatar based on your email address. re: New User to Web Tools - Basic Use Problem
  Gregg B
  Rick Strahl
  Jan 30, 2023 @ 11:57am

So, the example you sent me to add a collection works great; thanks! Now I need to 'stack' these collections along with other segments in the payload. I have tried but always seem to 'overwrite' the last one. This diagram depicts what it needs to look like. I assume the segments with the brackets are the 'collections'. How do I put them all together?

Gravatar is a globally recognized avatar based on your email address. re: New User to Web Tools - Basic Use Problem
  Rick Strahl
  Gregg B
  Jan 30, 2023 @ 01:19pm

Look Greg, you're going to have to do some of this work yourself. I'm not here to do your work for you... I've given you everything you need to know how to do this.

There's no such thing as stacking. It's just additional properties.

+++ Rick ---

© 1996-2024