Author Topic: .net Restful queries  (Read 653 times)

stanl

  • Pundit
  • *****
  • Posts: 939
.net Restful queries
« on: June 27, 2019, 05:28:09 am »
Consider this another learning experience.  I would like to set up a script using the WB CLR to return geocode results from: https://geocode.xyz


My understanding is queries are best made with urlencoded address.  I discovered 2 ways to encode [ script below ]. In looking at existing .net code it appears that the namespace System.Net.Http is required.  System.Net.Http.dll is on my laptop as a referenced assembly in VS Community 2019. However, ObjectClrOption() or ObjectClrNew() both return an error that the dll cannot be found. Google is full of problems with that assembly, so I'm sure it is not a WB problem that it cannot be used in a script. I can access the site with Powershell and encapsulate PS code within a WB script as the PS REST cmdlets are quite powerful. Any suggestions as to pursuing with WB CLR appreciated.
Code: Winbatch

; Winbatch 2018A - Prepare address for REST API call
;
;====================================================================================


;using last known address for Antonio Banderas
address = 'Baum Halls - 8388 Wilshire Blvd., Ste. 444 - Beverly Hills, CA 90211'
ObjectClrOption("useany", "System")


oNet = ObjectClrNew('System.Net.WebUtility')
encoded = oNet.UrlEncode(address)
Pause("Prepare address for REST API - with System.Net.WebUtility","address: ":address:@LF:"encoded: ":encoded)
oNet=0


ObjectClrOption("useany", "System.Web")
oNet = ObjectClrNew('System.Web.HttpUtility')
encoded = oNet.UrlEncode(address)
Pause("Prepare address for REST API - with System.Web.HttpUtility","address: ":address:@LF:"encoded: ":encoded)
oNet=0


Exit
 
 

td

  • Tech Support
  • *****
  • Posts: 3019
    • WinBatch
Re: .net Restful queries
« Reply #1 on: June 27, 2019, 07:04:07 am »
Maybe missing something (have been doing a lot of that lately) but this works on my system:

Code: Winbatch
ObjectClrOption("useany", "System.Net.Http")
objHttpClient = ObjectClrNew('System.Net.Http.HttpClient')
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

stanl

  • Pundit
  • *****
  • Posts: 939
Re: .net Restful queries
« Reply #2 on: June 27, 2019, 09:52:35 am »
Maybe missing something (have been doing a lot of that lately) but this works on my system:

Code: Winbatch
ObjectClrOption("useany", "System.Net.Http")
objHttpClient = ObjectClrNew('System.Net.Http.HttpClient')


Well, those lines errored when I wrote the post, but after a huge update of VS Studio 2019 the error is gone. BTW: that address is owned by Melanie Griffith.

td

  • Tech Support
  • *****
  • Posts: 3019
    • WinBatch
Re: .net Restful queries
« Reply #3 on: June 27, 2019, 02:18:42 pm »
The docs claim that System.Net.Http has been around since .NET Framework 4.5 and .NET Core 1.0.  So I guess you were either a bit behind or an earlier version was a bit buggy.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

stanl

  • Pundit
  • *****
  • Posts: 939
Re: .net Restful queries
« Reply #4 on: June 30, 2019, 04:08:18 am »
The docs claim that System.Net.Http has been around since .NET Framework 4.5 and .NET Core 1.0.  So I guess you were either a bit behind or an earlier version was a bit buggy.


My win 10 updates have a message that 1903 is coming but my pc is just not ready yet..... but as I said I can initialize the httpclient object, but can't go any further.


EDIT: I changed oClient.GetAsync(request,0) to oClient.GetAsync(request) and no longer errors. Will continue parsing the json object.


Code: Winbatch

; Winbatch 2018A - Prepare address for REST API call
;
;====================================================================================


gosub udfs
IntControl(73,1,0,0,0)
;using last known address for Antonio Banderas
url = 'https://geocode.xyz/'
address = 'Baum Halls - 8388 Wilshire Blvd., Ste. 444 - Beverly Hills, CA 90211'
ObjectClrOption("useany", "System")


oNet = ObjectClrNew('System.Net.WebUtility')
encoded = oNet.UrlEncode(address)
oNet=0


ObjectClrOption("useany", "System.Net.Http")
oClient = ObjectClrNew('System.Net.Http.HttpClient')


request =  url:encoded:'?json=1'
response = oClient.GetAsync(request,0) ;errors here, nethod not found
Pause("JSON Response",response)


oClient = 0


Exit
;====================================================================================


:WBERRORHANDLER
oClient=0
geterror()
Message("Error Encountered",errmsg)
Exit
;====================================================================================


:udfs
#DefineSubRoutine geterror()
   wberroradditionalinfo = wberrorarray[6]
   lasterr = wberrorarray[0]
   handlerline = wberrorarray[1]
   textstring = wberrorarray[5]
   linenumber = wberrorarray[8]
   errmsg = "Error: ":lasterr:@LF:textstring:@LF:"Line (":linenumber:")":@LF:wberroradditionalinfo
   Return(errmsg)
#EndSubRoutine
Return
 

stanl

  • Pundit
  • *****
  • Posts: 939
Re: .net Restful queries
« Reply #5 on: June 30, 2019, 06:00:44 am »
think I'm just digging myself a deeper hole -


EDITED: I added oMsg = ObjectClrNew('System.Net.Http.HttpResponseMessage') and the script runs w/out error. Still a ways to go.

Code: Winbatch

; Winbatch 2018A - Prepare address for REST API call
;
;====================================================================================
gosub udfs
IntControl(73,1,0,0,0)
;using last known address for Antonio Banderas
url = 'https://geocode.xyz/'
address = 'Baum Halls - 8388 Wilshire Blvd., Ste. 444 - Beverly Hills, CA 90211'
ObjectClrOption("useany", "System")


oNet = ObjectClrNew('System.Net.WebUtility')
encoded = oNet.UrlEncode(address)
oNet=0


ObjectClrOption("useany", "System.Net.Http")
oClient = ObjectClrNew('System.Net.Http.HttpClient')


request =  url:encoded:'?json=1'
;FilePut(dirscript():'geocode.txt',request) ;used to make manual request to check encoding


response = oClient.GetAsync(request).Result
TimeDelay(1) ;probably not needed


oMsg = ObjectClrNew('System.Net.Http.HttpResponseMessage')
Msg = "StatusCode: ":oMsg.StatusCode:@LF
Msg = Msg:"Reason Phrase: ":oMsg.ReasonPhrase:@LF
Msg = Msg:"Content: ":oMsg.Content




Pause("Status",Msg)


oClient = 0
Exit
;====================================================================================
:WBERRORHANDLER
oClient=0
geterror()
Message("Error Encountered",errmsg)
Exit
;====================================================================================
:udfs
#DefineSubRoutine geterror()
   wberroradditionalinfo = wberrorarray[6]
   lasterr = wberrorarray[0]
   handlerline = wberrorarray[1]
   textstring = wberrorarray[5]
   linenumber = wberrorarray[8]
   errmsg = "Error: ":lasterr:@LF:textstring:@LF:"Line (":linenumber:")":@LF:wberroradditionalinfo
   Return(errmsg)
#EndSubRoutine
Return
;====================================================================================

 

stanl

  • Pundit
  • *****
  • Posts: 939
Re: .net Restful queries
« Reply #6 on: July 01, 2019, 04:59:19 am »
I began to realize my initial scripting had some confusion between System.Net and Windows.Web Namespaces as they share similar classes and objects.  But using System.Net I can make requests either as


response = oClient.GetAsync(request).Result or response = oClient.GetStringAsync(request)


I can then run Pause("Result",response.ToString()) for either one.  The first returns a string with status 403: Forbidden; the second returns a string indicating a Task has been returned. In either case, the HttpResponseMessage returns 200: OK.


At this point, more interest than frustration.  I'm still in the freshman league when it comes to interpreting MSFT and .Net docs. So, Tony [or anyone else who follows this] be gentle.... I'm trying :o

td

  • Tech Support
  • *****
  • Posts: 3019
    • WinBatch
Re: .net Restful queries
« Reply #7 on: July 01, 2019, 02:39:55 pm »
The "oClient.GetAsync(request).Result" call returns the "System.Net.Http.HttpResponseMessage" object. You don't need to create one.  The resulting 403 error is likely because your request does not have the proper entity heads, your URL parameters are not quite right, or they simply don't want you there... 
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

td

  • Tech Support
  • *****
  • Posts: 3019
    • WinBatch
Re: .net Restful queries
« Reply #8 on: July 01, 2019, 02:57:41 pm »
Modified the URL a bit and did get a result using this replacement snippet in your code.
Code: Winbatch
response = oClient.GetAsync(request).Result

if Response.IsSuccessStatusCode
   TaskStr = Response.Content.ReadAsStringAsync()
   Content=TaskStr.Result
   Pause( "response",Content)
else
   Pause("response",Response.StatusCode)
endif
 
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

stanl

  • Pundit
  • *****
  • Posts: 939
Re: .net Restful queries
« Reply #9 on: July 02, 2019, 02:45:43 am »
Hmmmm....


so my request is: https://geocode.xyz/Baum+Halls+-+8388+Wilshire+Blvd.%2C+Ste.+444+-+Beverly+Hills%2C+CA+90211?json=1


If I open a browser and post it I get
Code: [Select]
{ "success": false, "error": { "code": "006", "message": "Request Throttled." } }


and if I leave off ?json=1 the entire HTML is returned. You mentioned tweaking the URL - was that a matter of re-formatting the request, or adding more .NET code earlier in the script? Your snippet [and thanks for that and the explanation] returns 403

td

  • Tech Support
  • *****
  • Posts: 3019
    • WinBatch
Re: .net Restful queries
« Reply #10 on: July 02, 2019, 07:32:14 am »
The 403 error is likely the result of the URL being incorrect or the site requiring something like an app key.   I don't know what the correct form is. You have to check with the site's documentation.  I just dumped the entire page to verify that I had identified the correct FCL syntax and class objects.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

stanl

  • Pundit
  • *****
  • Posts: 939
Re: .net Restful queries
« Reply #11 on: July 02, 2019, 09:18:04 am »
Thanks.  It does work in Powershell. Only thing different 'session' is referenced,


Code: [Select]

'One Microsoft Way, Redmond',
'Baum Halls - 8388 Wilshire Blvd., Ste. 444 - Beverly Hills, CA 90211' |
 ForEach-Object -Begin {$url = 'https://geocode.xyz'
   $null = Invoke-RestMethod $url -S session
 } -Process {
   $address = $_
   $encoded = [Net.WebUtility]::UrlEncode($address )
   Invoke-RestMethod "$url/${encoded}?json=1" -W $session|
     ForEach-Object {
       [PSCustomObject]@{
         Address = $address
         Long = $_.longt
         Lat = $_.latt
       }
     }
 }

JTaylor

  • Pundit
  • *****
  • Posts: 1015
    • Data & Stuff Inc.
Re: .net Restful queries
« Reply #12 on: July 02, 2019, 09:25:30 am »

td

  • Tech Support
  • *****
  • Posts: 3019
    • WinBatch
Re: .net Restful queries
« Reply #13 on: July 02, 2019, 11:18:32 am »
If it's not the URL then it could be a header problem or simply the site does not like some http messages the FCL class is sending.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

JTaylor

  • Pundit
  • *****
  • Posts: 1015
    • Data & Stuff Inc.
Re: .net Restful queries
« Reply #14 on: July 02, 2019, 12:14:56 pm »
That address seems a bit screwy in regards to the geocode service.  It always switches to 9107 Wilshire on me so I used my address and it returns a clean, accurate response on the web.   Oddly enough it returns the webpage with the correct mapping via WinBatch rather than the JSON.   Not sure this helps anything but I tried :)


Jim

td

  • Tech Support
  • *****
  • Posts: 3019
    • WinBatch
Re: .net Restful queries
« Reply #15 on: July 02, 2019, 01:31:17 pm »
Thanks.  It does work in Powershell. Only thing different 'session' is referenced,


Code: [Select]

'One Microsoft Way, Redmond',
'Baum Halls - 8388 Wilshire Blvd., Ste. 444 - Beverly Hills, CA 90211' |
 ForEach-Object -Begin {$url = 'https://geocode.xyz'
   $null = Invoke-RestMethod $url -S session
 } -Process {
   $address = $_
   $encoded = [Net.WebUtility]::UrlEncode($address )
   Invoke-RestMethod "$url/${encoded}?json=1" -W $session|
     ForEach-Object {
       [PSCustomObject]@{
         Address = $address
         Long = $_.longt
         Lat = $_.latt
       }
     }
 }

There is more than "session" being referenced that is different.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

stanl

  • Pundit
  • *****
  • Posts: 939
Re: .net Restful queries
« Reply #16 on: July 02, 2019, 02:28:31 pm »
There is more than "session" being referenced that is different.


Yes, after the results are returned, the JSON is parsed.  But, funny if I click on the url I posted or Jim followed up with the address comes up as 9107 Wilshire, but then I click again and it comes up 'throttled'. The site, I believe is the Google Geocode site and according to on thread I read -  Last year, Google changed their terms and requires an individual API key now to use their geocode API.


and the encoded REST query was purported as a alternative. Oh, and Jim - when you said it worked with WB rather than json where you referring to a COM script, i.e. WINHTTP:

JTaylor

  • Pundit
  • *****
  • Posts: 1015
    • Data & Stuff Inc.
Re: .net Restful queries
« Reply #17 on: July 02, 2019, 02:32:53 pm »
I was using the script you provided.     I meant that in the browser the url returned JSON results.  In the script it returns the web page with the correct results.

Jim

stanl

  • Pundit
  • *****
  • Posts: 939
Re: .net Restful queries
« Reply #18 on: July 02, 2019, 03:34:58 pm »
Finally!  A little clunky but added a For...Next loop with slight Timedelay() and I get the json. Now to try to parse with Newtonsoft.
Code: Winbatch

; Winbatch 2018A - Prepare address for REST API call
; Stan Littlefield - July 2, 2019
;====================================================================================
gosub udfs
IntControl(73,1,0,0,0)
;using last known address for Antonio Banderas
url = 'https://geocode.xyz/'
address = 'Baum Halls - 8388 Wilshire Blvd., Ste. 444 - Beverly Hills, CA 90211'


ObjectClrOption("useany", "System")


oNet = ObjectClrNew('System.Net.WebUtility')
encoded = oNet.UrlEncode(address)
oNet=0


ObjectClrOption("useany", "System.Net.Http")
oClient = ObjectClrNew('System.Net.Http.HttpClient')


request =  url:encoded:'?json=1'      ;'?json=1'


FilePut(dirscript():'geocode.txt',request) ;used to make manual request to check encoding


success =0


For i = 1 To 10
   response = oClient.GetAsync(request).Result


   if Response.IsSuccessStatusCode
      TaskStr = Response.Content.ReadAsStringAsync()
      Content=TaskStr.Result
      Pause( "response",Content)
      success = 1
      Break
   Endif
   Timedelay(1)
Next


If ! success Then Pause("response",Response.StatusCode)








oClient = 0
Exit
;====================================================================================
:WBERRORHANDLER
oClient=0
geterror()
Message("Error Encountered",errmsg)
Exit
;====================================================================================
:udfs
#DefineSubRoutine geterror()
   wberroradditionalinfo = wberrorarray[6]
   lasterr = wberrorarray[0]
   handlerline = wberrorarray[1]
   textstring = wberrorarray[5]
   linenumber = wberrorarray[8]
   errmsg = "Error: ":lasterr:@LF:textstring:@LF:"Line (":linenumber:")":@LF:wberroradditionalinfo
   Return(errmsg)
#EndSubRoutine
Return
;====================================================================================


 

td

  • Tech Support
  • *****
  • Posts: 3019
    • WinBatch
Re: .net Restful queries
« Reply #19 on: July 02, 2019, 04:05:39 pm »
A simple synchronization problem with a clever workaround.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

stanl

  • Pundit
  • *****
  • Posts: 939
Re: .net Restful queries
« Reply #20 on: July 03, 2019, 02:35:47 am »
A simple tweak and you can do the reverse - find address based on lat/long. No encoding is required and it appears it might even return a phone number
Code: Winbatch

; Winbatch 2018A - Obtain Address from Latitude, Longitude
; Stan Littlefield - July 3, 2019
;====================================================================================
gosub udfs
IntControl(73,1,0,0,0)
url = 'https://geocode.xyz/'
LatLong = '34.06711,-118.39047'
ObjectClrOption("useany", "System")
;encoding is not required


ObjectClrOption("useany", "System.Net.Http")
oClient = ObjectClrNew('System.Net.Http.HttpClient')
request =  url:LatLong:'?geoit=json'  
success =0


For i = 1 To 10
   response = oClient.GetAsync(request).Result
   if Response.IsSuccessStatusCode
      TaskStr = Response.Content.ReadAsStringAsync()
      Content=TaskStr.Result
      Pause( "response",Content)
      success = 1
      Break
   Endif
   Timedelay(1)
Next


If ! success Then Pause("response",Response.StatusCode)


oClient = 0
Exit
;====================================================================================
:WBERRORHANDLER
oClient=0
geterror()
Message("Error Encountered",errmsg)
Exit
;====================================================================================
:udfs
#DefineSubRoutine geterror()
   wberroradditionalinfo = wberrorarray[6]
   lasterr = wberrorarray[0]
   handlerline = wberrorarray[1]
   textstring = wberrorarray[5]
   linenumber = wberrorarray[8]
   errmsg = "Error: ":lasterr:@LF:textstring:@LF:"Line (":linenumber:")":@LF:wberroradditionalinfo
   Return(errmsg)
#EndSubRoutine
Return
;====================================================================================


 

stanl

  • Pundit
  • *****
  • Posts: 939
Re: .net Restful queries
« Reply #21 on: July 04, 2019, 05:19:46 am »
NOTES:
  • The script uses 'free' access to the site, and my initial issues were due to this restriction in their docs: There are currently no usage limits but response times on the free ports are normally throttled to no more than 1 request per second for all un-authenticated users combined.
  • in addition to json=1 for a return you can use ?geoit=csv or ?geoit=xml
  • I wanted to extend the CLR stuff and parse the json return. I tried both ObjectClrOption("useany", "System.Web.Helpers") and ObjectClrOption("useany", "System.Web.Script.Serialization") but received an error that the dll could not be found, even though they are in the VS 2019 folder structure - Google searches and stackoverflow say I'm not alone on this

td

  • Tech Support
  • *****
  • Posts: 3019
    • WinBatch
Re: .net Restful queries
« Reply #22 on: July 04, 2019, 08:31:59 am »
You can't load the assemblies because they are not in the GAC.  For example, on my system I would need to do the following:

Code: Winbatch
ObjectClrOption('Appbase', 'C:\Program Files (x86)\Microsoft Visual Studio\Shared\Packages\Microsoft.AspNet.WebPages.3.2.7\lib\net45')
ObjectClrOption("useany", "System.Web.Helpers")
 

Of course you can move the assembly to a different location or install it into the GAC.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

stanl

  • Pundit
  • *****
  • Posts: 939
Re: .net Restful queries
« Reply #23 on: July 04, 2019, 12:03:19 pm »
That would have been my next question. But I was worried about when to call 'appbase' in the script - i.e. if called early would it override subsequent calls to ObjectClrOption() that might be in the GAC? For example:
Code: Winbatch

ObjectClrOption("useany", "System")
ObjectClrOption('Appbase', 'C:\Program Files (x86)\Microsoft Visual Studio\Shared\Packages\Microsoft.AspNet.WebPages.3.2.7\lib\net45')
 

will error that 'Runtime has already been loaded'.  Who's on First...What's on second : you know the drill


EDIT: But put it in the GAC - thanks


C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.7.2 Tools>gacutil /i "C:\Program Files (x86)\Microsoft Visual Studio\Shared\Packages\Microsoft.AspNet.WebPages.3.2.7\lib\net45\System.Web.Helpers.dll"
Microsoft (R) .NET Global Assembly Cache Utility.  Version 4.0.30319.0
Copyright (c) Microsoft Corporation.  All rights reserved.


Assembly successfully added to the cache



td

  • Tech Support
  • *****
  • Posts: 3019
    • WinBatch
Re: .net Restful queries
« Reply #24 on: July 04, 2019, 05:40:51 pm »
Setting the "appbase" should not affect the loading of GAC assemblies.  However, you need to set "appBase" at the beginning of your script.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

stanl

  • Pundit
  • *****
  • Posts: 939
Re: .net Restful queries
« Reply #25 on: July 05, 2019, 02:31:59 am »
Setting the "appbase" should not affect the loading of GAC assemblies.  However, you need to set "appBase" at the beginning of your script.


Thanks. Added a UDS to call the System.Web.Helpers.Json.Decode() method and that errors as 'Ambiguous Match Found'. This seems to be a problem with the same name of an element with different cases.
Code: Winbatch

; Winbatch 2018A - Prepare address for REST API call
; Stan Littlefield - July 2, 2019
;====================================================================================
gosub udfs
IntControl(73,1,0,0,0)
;using last known address for Antonio Banderas
url = 'https://geocode.xyz/'
fmts = '?json=1,?geoit=xml,?geoit=csv'
fmt = Itemextract(1,fmts,",")
address = 'Baum Halls - 8388 Wilshire Blvd., Ste. 444 - Beverly Hills, CA 90211'      


ObjectClrOption("useany", "System")


oNet = ObjectClrNew('System.Net.WebUtility')
encoded = oNet.UrlEncode(address)
oNet=0


ObjectClrOption("useany", "System.Net.Http")
oClient = ObjectClrNew('System.Net.Http.HttpClient')


request =  url:encoded:fmt    
FilePut(dirscript():'geocode.txt',request) ;used to make manual request to check encoding


success =0


For i = 1 To 10
   response = oClient.GetAsync(request).Result


   if Response.IsSuccessStatusCode
      TaskStr = Response.Content.ReadAsStringAsync()
      Content=TaskStr.Result
      If fmt== '?json=1'
         Pause("response",parsejson())
      Else
         Pause( "response",Content)
      Endif
      success = 1
      Break
   Endif
   Timedelay(1)
Next


If ! success Then Pause("response",Response.StatusCode)








oClient = 0
Exit
;====================================================================================
:WBERRORHANDLER
oClient=0
geterror()
Message("Error Encountered",errmsg)
Exit
;====================================================================================
:udfs
#DefineSubRoutine geterror()
   wberroradditionalinfo = wberrorarray[6]
   lasterr = wberrorarray[0]
   handlerline = wberrorarray[1]
   textstring = wberrorarray[5]
   linenumber = wberrorarray[8]
   errmsg = "Error: ":lasterr:@LF:textstring:@LF:"Line (":linenumber:")":@LF:wberroradditionalinfo
   Return(errmsg)
#EndSubRoutine


#DefineSubRoutine parsejson()
   IntControl(73,1,0,0,0)
   ObjectClrOption("useany", "System.Web.Helpers")
   oJson = ObjectClrNew('System.Web.Helpers.Json')
   result= oJson.Decode(Content)
   Pause("decoded",ObjectTypeGet(result))
   oJson=0
   Return(result)
   
   :WBERRORHANDLER
   oJson=0
   oClient=0
   geterror()
   Message("Error Encountered",errmsg)
   Exit
#EndSubRoutine
Return
;====================================================================================


 

td

  • Tech Support
  • *****
  • Posts: 3019
    • WinBatch
Re: .net Restful queries
« Reply #26 on: July 05, 2019, 09:15:53 am »
I think you have encountered a side-effect of generic programming. Mscorelib can't resolve the method signature because of the template based return type.  Don't know that there is a workaround that would allow you to call the "Decode" method directly.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

stanl

  • Pundit
  • *****
  • Posts: 939
Re: .net Restful queries
« Reply #27 on: July 05, 2019, 09:26:15 am »
I think you have encountered a side-effect of generic programming. Mscorelib can't resolve the method signature because of the template based return type.  Don't know that there is a workaround that would allow you to call the "Decode" method directly.


Yeah. Tested it directly [below]. Maybe try serialization class next. Funny that Json is so poplar and .net json parsing is so frustrating.
Code: Winbatch

j = '{   "standard" : {      "stnumber" : "9107",      "addresst" : "WILSHIRE BLVD",      "postal" : "90210-5596",      "region" '
j = j: ': "CA",      "prov" : "US",      "city" : "BEVERLY HILLS",      "countryname" : "United States of America",      "confidence" : "0.7"   }, '  
j = j: '"longt" : "-118.39047",   "alt" : {},   "elevation" : {},   "latt" : "34.06711"}'
ObjectClrOption("useany", "System.Web.Helpers")
oJ = ObjectClrNew('System.Web.Helpers.Json')
myj= oJ.Decode(j)
Pause("decoded",ObjectTypeGet(myj))
oj=0
Exit
 

td

  • Tech Support
  • *****
  • Posts: 3019
    • WinBatch
Re: .net Restful queries
« Reply #28 on: July 05, 2019, 10:21:02 am »
I suppose you could try wrapping the Parse method in a c# class that you compile on the fly or into an assembly that you load and call from WinBatch.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

stanl

  • Pundit
  • *****
  • Posts: 939
Re: .net Restful queries
« Reply #29 on: July 06, 2019, 03:31:03 am »
I suppose you could try wrapping the Parse method in a c# class that you compile on the fly or into an assembly that you load and call from WinBatch.


Or I suppose I could revert to COM and dig out an old function I dug up for a script I put together with Delev in 2012. It does a fair job with the JSON. but StrReplace() lines fail for invalid Null Character. I checked the tech db for removing nulls but cam up blank.
Code: Winbatch

; Winbatch 2018A - Prepare address for REST API call
; Stan Littlefield - July 2, 2019
;
; Revision: CreateObject ("MSScriptControl.ScriptControl")  used for JSON
;           instead of .net class
;====================================================================================
gosub udfs
IntControl(73,1,0,0,0)
;using last known address for Antonio Banderas
url = 'https://geocode.xyz/'
fmts = '?json=1,?geoit=xml,?geoit=csv'
fmt = Itemextract(1,fmts,",")
address = 'Baum Halls - 8388 Wilshire Blvd., Ste. 444 - Beverly Hills, CA 90211'      


ObjectClrOption("useany", "System")


oNet = ObjectClrNew('System.Net.WebUtility')
encoded = oNet.UrlEncode(address)
oNet=0


ObjectClrOption("useany", "System.Net.Http")
oClient = ObjectClrNew('System.Net.Http.HttpClient')


request =  url:encoded:fmt    
;FilePut(dirscript():'geocode.txt',request) ;used to make manual request to check encoding


success =0


For i = 1 To 10
   response = oClient.GetAsync(request).Result


   if Response.IsSuccessStatusCode
      TaskStr = Response.Content.ReadAsStringAsync()
      Ct=TaskStr.Result
      ;FilePut(dirscript():'results.txt',Ct)
      If fmt== '?json=1'
         Ct = GetJSON(Ct)
         ;Ct = StrReplace(Ct,"|",""}
         ;Ct = StrReplace(Ct,",","="}
         ;Ct = StrReplace(Ct,@LF,@CRLF}
         FilePut(dirscript():'results.txt',Ct)
         Pause("response",Ct)
      Else
         Pause( "response",Content)
      Endif
      success = 1
      Break
   Endif
   Timedelay(1)
Next
If ! success Then Pause("response",Response.StatusCode)
oClient = 0
Exit
;====================================================================================
:WBERRORHANDLER
oClient=0
geterror()
Message("Error Encountered",errmsg)
Exit
;====================================================================================
:udfs
#DefineSubRoutine geterror()
   wberroradditionalinfo = wberrorarray[6]
   lasterr = wberrorarray[0]
   handlerline = wberrorarray[1]
   textstring = wberrorarray[5]
   linenumber = wberrorarray[8]
   errmsg = "Error: ":lasterr:@LF:textstring:@LF:"Line (":linenumber:")":@LF:wberroradditionalinfo
   Return(errmsg)
#EndSubRoutine




#DefineFunction GetJSON(strJSON)
If strJSON == "" Then Return ""
objJSC = CreateObject ("MSScriptControl.ScriptControl")
objJSC.Language = "JScript"
objJSC.AddCode(: `function json2txt(obj,path){var txt='';for(var key in obj){if(obj.hasOwnProperty(key)){if('object'==typeof(obj[key])){txt+=json2txt(obj[key],path+(path?'|':'')+key);}else{txt+=path+'|'+key+','+obj[key]+'\n';}}}return txt;}`)
Return objJSC.Eval(: `json2txt(` : strJSON : `,'')`)
; JS code from Patrick Fisher at "http://stackoverflow.com/questions/10221229/list-all-keys-and-values-of-json" ; 2012-04-19T03:48:24.
#EndFunction
Return
;====================================================================================


 

td

  • Tech Support
  • *****
  • Posts: 3019
    • WinBatch
Re: .net Restful queries
« Reply #30 on: July 06, 2019, 09:44:30 am »
Likely missing something again but not sure what you mean by "StrReplace() lines fail for invalid Null Character".  I uncommented the three StrReplace lines in your script, correct the right-brace typo, and the script completed without error.

I am still interested in discovering what MSFT's Decode method produces as a data object.  Might take a hack at this weekend if time permits.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

stanl

  • Pundit
  • *****
  • Posts: 939
Re: .net Restful queries
« Reply #31 on: July 07, 2019, 06:40:09 am »
Likely missing something again but not sure what you mean by "StrReplace() lines fail for invalid Null Character".  I uncommented the three StrReplace lines in your script, correct the right-brace typo, and the script completed without error.

I am still interested in discovering what MSFT's Decode method produces as a data object.  Might take a hack at this weekend if time permits.


Yeah, I fat-fingered the braces. Been having problems getting to the forum since my last post. Kept getting 404 server error.

td

  • Tech Support
  • *****
  • Posts: 3019
    • WinBatch
Re: .net Restful queries
« Reply #32 on: July 07, 2019, 05:44:29 pm »
Notices the same problem this afternoon.  Either our ISP or DNS provider is having "issues."
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

stanl

  • Pundit
  • *****
  • Posts: 939
Re: .net Restful queries
« Reply #33 on: July 07, 2019, 05:46:05 pm »
For fun instead of GetAsync I tried:
Code: Winbatch
response = oClient.PostAsync(url,encoded:fmt).Result
 


and that returned 'unsupported variant type'

td

  • Tech Support
  • *****
  • Posts: 3019
    • WinBatch
Re: .net Restful queries
« Reply #34 on: July 08, 2019, 07:42:06 am »
Not sure what you attempting to do with the "encoded:fmt" parameter but "encoded" certainly isn't a valid variant type.  In order to supply parameter type information with a call to a class method, type information must be a valid variant type or a valid fully qualified .Net assembly type.  For example, "System.Net.Http.HttpContent" is the type indicated for the second parameter to the PostAsync method.  Of course, the parameter's value would also need to be an instance of an HttpContent object.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade