VBA GET request failing, bad format? - vba

I'm a novice and your help has been amazing so far! I have an issue with a GET request for SSO authentication in an Excel Visual Basic script. The API says to send the GET request to:
https://services.example.com/API/Security.svc/SSOSiteLogin/siteId/enterpriseGuid/authToken/timezoneOffset
Where the values for siteID, enterpriseGUID, authToken, and timezoneOffset have all been obtained by previous GET requests, which have worked fine. When I send the final GET request for a security token, it returns:
{"Detail":"SSOSiteLogin failed.Input string was not in a correct format."}
Here is my relevant code:
Dim hreq As New WinHttpRequest
Dim response As String
Dim URL As String
'get security token
URL = "https://services.example.com/API/Security.svc/SSOSiteLogin/siteID/enterpriseGUID/" & authToken & "/null"
hreq.Open "GET", URL, False
hreq.Send
response = hreq.ResponseText
Range("A13") = response
The siteID and enterpriseGUID variables are input into the code, and the authToken is stored from an earlier POST request. The last value, timezoneOffset, is given as "null" from an earlier request so I've been typing "/null" at the end but I'm concerned that's what's triggering the incorrect format response. Anything else just returns a total error from the server though.
Any ideas? Thank you in advance!

I had put the values into cells and was sending the GET request as "Range("E5") & "/" & Range("E6") & "/", etc. so that I could try a couple of debugging issues without having to go to the VBA editor and for some reason that worked! I ended up using the string "null", too. If anyone knows why this worked and inputting it all as one string doesn't I'd be interested to find out.

Related

VB macro changing encoding on REST request

I have an excel file with a button associated to a VB macro like this:
Sub button_macro()
Set MyRequest = CreateObject("WinHttp.WinHttpRequest.5.1")
MyRequest.Open "GET", "http://theurl/service?param=""Gestión"""
MyRequest.Send
End Sub
But the response I get is something like:
"Gestión" is not a valid value for param.
How can I avoid VB converting the 'ó' character to another encoding?
If I send the request via browser like:
http://theurl/service?param="Gestión"
The service answer as desired.
EDIT:
Curiously MsgBox "Código único" works as expected showing the 'ó' and 'ú' characters correctly.
It works in the browser because the browser encodes the request for you - you can see that if you use your browser's Developer tools - eg for your "example" URL of
http://theurl/service?param="Gestión"
I see
http://theurl/service?param=%22Gesti%C3%B3n%22
You can encode your parameters using (eg) the UTF-supporting method from the accepted answer here: How can I URL encode a string in Excel VBA?

Why do i get "Argument is not optional" error on simple url call?

My goal is to check the internet connecton in VBA but when i try to call a url with request.open I get the error message "Argument is not optional".
Sadly internet research has no yielded any results.
This is my code:
On Error GoTo NoConnectionErrorHandling
Dim Request As MSXML2.XMLHTTP60
Request.Open "http://www.google.com"
Request.send
MsgBox Request.Status
It hangs itself in the third line of the shown code.
I hope someone can help me as i have very very little experience in VBA yet.
You have to specify the type of the request. It can be "GET", "POST" or something else.
See here for the open Method:
https://msdn.microsoft.com/en-us/library/ms757849(v=vs.85).aspx
These are the parameters:
bstrMethod
The HTTP method used to open the connection, such as GET, POST, PUT, or PROPFIND. For XMLHTTP, this parameter is not case-sensitive. The verbs TRACE and TRACK are not allowed when IXMLHTTPRequest is hosted in the browser. What is the difference between POST and GET?
bstrUrl
The requested URL. This can be either an absolute URL, such as "http://Myserver/Mypath/Myfile.asp", or a relative URL, such as "../MyPath/MyFile.asp".
varAsync[optional]
bstrUser[optional]
bstrPassword[optional]
As you see, the method needs at least two parameters (the other 3 are optional) thus 1 is not enough.
You need to declare Request with the keyword New. Thus, something like the following piece works:
Public Sub TestMe()
Dim Request As New MSXML2.XMLHTTP60
Request.Open "GET", "http://www.bbc.com"
Request.send
MsgBox Request.Status
End Sub
Whenever you are using libraries outside the standard VBA libraries it is a good idea to do one of the following 2:
Provide information for the library:
Use late binding:
Dim Request As Object
Set Request = CreateObject("Msxml2.ServerXMLHTTP.6.0")

Submitting HTML values using VBA

Using the CreateObject("msxml2.xmlhttp") to extract information from a web-page, I've discovered that null response from getElementsByTagName("table") is experienced when a login is required on said web-page.
I've attempted to overcome this by using the following to set username/password for the login page:
oDom.getElementById("login-form-username").Value = strUser
oDom.getElementById("login-form-password").Value = strPwd
I've subsequently attempted to submit the information using:
oDom.getElementById("login-form-submit").Click
Unfortunately, the .Click does not seem to work. Is there anything else required to in order to submit the information? The strUser and strPwd values are input from InputBox.
Many thanks in advance
G

My code behaves weird

So... here's the thing...
I'm connected through sky, which have dynamic IPs and my IP changes once in a while. I'm running a small website from home, the website has, among other things, three video streams from my ip cameras. Now, I don't want to update my code every time the ip changes, so there is this bit at the top of my file:
Response.Buffer = True
Dim objXMLHTTP, xml
Set xml = Server.CreateObject("Microsoft.XMLHTTP")
xml.Open "GET", "http://myip.dnsomatic.com/", False
xml.Send
externalIP = xml.responseText
Set xml = Nothing
My ip changed a while ago, but above code was returning my old IP! When I visited http://myip.dnsomatic.com/, it shown the correct, new IP. The situation persisted as long as I didn't restart my machine. I would like to know why the code behaves like that? Why it doesn't return correct IP right away?
There is one more thing I do not understand... My website has a comments feature, where users can leave a comment. My addComment.asp file checks if the session expired first:
if Session("userID") = "" or Session("username") = "" then
Response.Write("<SCRIPT LANGUAGE=JavaScript>")
Response.Write("alert('Your session has expired...');")
Response.Write("window.location.href='index.html';")
Response.Write("</SCRIPT>")
end if
If the session hasn't expired, the comment is added to the database and the page is updated, but if the session expired, it doesn't go back to index.html, instead, the INSERT INTO statement, which I use to insert the comment into corresponding table, throws an error! That statement is way below above code, theoretically it should never be executed. Any ideas?
I should also add that if the above code is modified following way:
if Session("userID") = "" or Session("username") = "" then
Response.Redirect("index.html")
end if
everything works fine in both cases (session expired and not expired), but I would like a message telling the user about the expiration to pop up. Here's the INSERT INTO statement, which I don't think contains any errors:
conn.Open connStr
commText = "INSERT INTO Messages (ID,
userID,
messageDate,
messageText)
VALUES (" & (recordsQty + 1) & ",
" & currentUserID & ",
#" & Now & "#,
'" & commentText & "')"
conn.Open connStr
conn.Execute commText
conn.Close()
This is just a theory, but I'm guessing that you're getting stale results because it's being cached somewhere. Untested code, but I believe this will solve your problem if it's caching:
Set xml = Server.CreateObject("Microsoft.XMLHTTP")
xml.Open "GET", "http://myip.dnsomatic.com/", False
xml.setRequestHeader "If-None-­Match", "some-random-string"
xml.setRequestHeader "Cache-Co­ntrol", "no-cache,max-age=0"
xml.setRequestHeader "Pragma",­ "no-cache"
xml.Send
As for continuing to get an error after redirecting, the mistake you're making is not separating server-side from client-side execution of code. Unless aborted, the server-side code will continue to execute to the end. Response.Redirect(String) aborts the execution, although not in a particularly clean way: http://msdn.microsoft.com/en-us/library/t9dwyts4%28v=vs.110%29.aspx
It's much better to modify your code so that it can continue all the way to the end. For example, this may not be pretty depending on how much code you have, but putting the non-redirect path inside of an else block of the if Session("userID") ... block would work.
Edit: I don't have the rep to post comments, but I don't believe this is a DNS caching issue at all, as the myip.dnsomatic.com is simply returning the IP of the client it's serving, which you're then, I assume, directly connecting to. If that's the case, DNS (other than resolving the myip.dnsomatic.com name) isn't involved at all.

ASPTwitter library fails when using special characters

I am trying to update an old ASP classic Twitter program that my work currently uses to use the new OAUTH. I am not an ASP programmer but I managed to find the ASPTwitter library posted online by Tim Acheson at http://www.timacheson.com/Blog/2013/jun/asptwitter
Everything works, as we have our own code searching our database and passing on a built string to the ASPTwitter code to tweet.
The catch is that it will fail with the
{"errors":[{"message":"Could not authenticate you","code":32}]}
error message if there is so much as a "." period in the string. Every possible special character besides letters and numbers causes a fail.
We have many posts that will include various symbols as well as URLs.
I have searched all over and have not been able to find a solution. Comments on Tim's site have mentioned it but no solutions yet. Everyone here has been very helpful so I was hoping someone might have a solution.
I can't post the code as there are about 6 files and I don't know which one is causing the issue.
Thank you so much for the help!
Edit:
This is a block of the 300+ line file where the issue happens, I hope that the cause can be found here too.
' Gets bearer token for application-only authentication from Twitter API 1.1.
' Application-user authentication: https://dev.twitter.com/docs/auth/using-oauth
' and: https://dev.twitter.com/docs/auth/authorizing-request
' API endpoint statuses/update (post a tweet): https://dev.twitter.com/docs/api/1.1/post/statuses/update
Private Function UpdateStatusJSON(sStatus)
Dim sURL : sURL = API_BASE_URL + "/1.1/statuses/update.json"
Dim oXmlHttp: Set oXmlHttp = Server.CreateObject("MSXML2.ServerXMLHTTP")
oXmlHttp.open "POST", sURL, False
sStatus = "this is from the ASPTwitter dot asp file"
oXmlHttp.setRequestHeader "Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"
oXmlHttp.setRequestHeader "User-Agent", "emiratesjobpost.com"
oXmlHttp.setRequestHeader "Authorization", "OAuth " & GetOAuthHeader(sURL, sStatus)
oXmlHttp.send "status=" & Server.URLEncode(sStatus) ' Encoded spaces as + in request body.
UpdateStatusJSON = oXmlHttp.responseText
Set oXmlHttp = Nothing
REM: A JSON viewer can be useful here: http://www.jsoneditoronline.org/
' To fix error message "Read-only application cannot POST" go to your application's "Application Type" settings at dev.twitter.com/apps and set "Access" to "Read and Write".
' After changing access to read/write you must click the button to generate new auth tokens and then use those.
Response.Write "<textarea cols=""100"" rows=""3"" >" & UpdateStatusJSON & "</textarea>" : Response.Flush()
End Function
If I replace the "dot" with "." in the "sStatus" line, it breaks
Do your pages use UTF-8 encoding? Open them in Notepad, select save as from the file menu, and if ansi coding is selected then change it to UTF-8.
See this link for more things you can do
http://www.hanselman.com/blog/InternationalizationAndClassicASP.aspx