Need help in solving error in HTTP GET request - vb.net

Need help in solving error in HTTP GET request [closed]
I have the following code in VB.NET framework which should pull the data in json format and add it to a list view control using GET request. However I am getting following error:
System.Threading.Tasks.Task.FromResult(System.Net.Http.HttpResponseMessage)
Dim client = New HttpClient()
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{Subscription-Key}")
Dim uri = "https://example.com/" & SearchKey
Dim response = client.GetAsync(uri)
lstMer.Items.Add(response.ToString)
Initially I wrote the following code in VBA and it was working fine:
Dim jsonText as String
Set req = New MSXML2.ServerXMLHTTP60
key_id = "{Subscription-Key}"
key_header_name = "Subscription-Key-Id"
liveURL = "https://example.com/" & SearchKey
req.Open "GET", liveURL, False
req.setRequestHeader {Subscription-Key-Id}, {Subscription-Key}
req.setRequestHeader "Host", "site Address"
req.send
jsonText = req.responseText
The requirement is to get the headers from URL and fill a list view.

I think I understand. You don't get an error
System.Threading.Tasks.Task.FromResult(System.Net.Http.HttpResponseMessage)
rather you get that as a result of response.ToString(). This is because you are calling client.GetAsync(uri) directly, which returns a Task.FromResult<TResult>. However, it is meant to be run async, and there are some convenient keywords for achieving this, namely Async / Await. If you await the task, instead of returning a Task.FromResult<TResult>, it will return a TResult. So change your code to do just that
Private Async Sub Foo()
Dim client = New HttpClient()
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{Subscription-Key}")
Dim uri = "https://example.com/" & SearchKey
Dim response = Await client.GetAsync(uri)
lstMer.Items.Add(response.ToString)
End Sub
See HttpClient.GetAsync and about what it returns Task.FromResult

Related

RestSharp call to eBay oauth2 user token

I am trying to get eBay user tokens for my users using the identity api. I finally got it to work in Postman. Converted the call from Postman to a restsharp call from a vb.net test app. The Postman call works, the VB call returns "404 Not Found". Looked at the two calls using Fiddler. The only difference I can see is that the Postman call goes to:
"POST https://api.sandbox.ebay.com/identity/v1/oauth2/token";
and the VB app call goes to
"POST https://api.sandbox.ebay.com/identity/v1/oauth2/token/1"
It would appear that somewhere the VB app is appending "/1" to the api url. Not sure where this is occurring as I can step through the code as it executes and don't see it.
Is there a property in RestSharp that might cause this value to be appended?
EDIT added code. This code is supposed to return a user token and refresh token from eBay. It is taken pretty much from Postman with mods to work with the latest version.
Async Sub RSGetCode(sCode As String)
Dim client As RestClient = New RestClient("https://api.sandbox.ebay.com/identity/v1/oauth2/token")
Dim request As RestRequest = New RestRequest(Method.Post)
sCode = WebUtility.UrlDecode(sCode)
With request
.AddHeader("Content-Type", "application/x-www-form-urlencoded")
.AddHeader("Authorization", "Basic TXVycGh5c0MtNzYxNy00ZGRmLTk5N2ItOD..........................")
.AddParameter("grant_type", "authorization_code")
.AddParameter("code", sCode)
.AddParameter("redirect_uri", "Murphys_Creativ-Mu...........")
.AddParameter("Scope", "https://api.ebay.com/oauth/api_scope/sell.inventory")
End With
Dim responce = Await client.PostAsync(request)
'Dim responce = Await client.ExecuteAsync(request)
Dim sR As String = responce.Content
End Sub```
I got it to work by slightly reformating the code. See below.
Async Sub PostRestCode(sCode As String)
Dim client As RestClient = New RestClient("https://api.sandbox.ebay.com")
Dim request As RestRequest = New RestRequest("identity/v1/oauth2/token", Method.Post)
With request
.AddHeader("Content-Type", "application/x-www-form-urlencoded")
.AddHeader("Authorization", "Basic TXVycGh5c0MtNzYxNy00ZGRmLTk5N2ItODc2OGMzZWZkYT..............................")
.AddParameter("grant_type", "authorization_code")
.AddParameter("code", sCode) '"v^1.1#i^1#I^3#p^3#f^0#r^1#t^Ul41Xzg6NEN.......................................")
.AddParameter("redirect_uri", "Murphys_Creativ-Mu......................")
.AddParameter("Scope", "https://api.ebay.com/oauth/api_scope/sell.inventory")
End With
Dim responce = Await client.PostAsync(request)
'Dim responce = Await client.ExecuteAsync(request)
Dim sR As String = responce.Content
End Sub

Catch the POST Request Response and the Redirected URL from XMLHTTP request with VBA

I'm trying to catch a Response to a POST Request using XMLHTTP using the code below
Dim XMLPage As New MSXML2.XMLHTTP60
Dim HTMLDoc As New MSHTML.HTMLDocument
Dim htmlEle1 As MSHTML.IHTMLElement
Dim htmlEle2 As MSHTML.IHTMLElement
Dim URL As String
Dim elemValue As String
URL = "https://www.informadb.pt/pt/pesquisa/?search=500004064"
XMLPage.Open "GET", URL, False
XMLPage.send
HTMLDoc.body.innerHTML = XMLPage.responseText
For Each htmlEle1 In HTMLDoc.getElementsByTagName("div")
Debug.Print htmlEle1.className
If htmlEle1.className = "styles__SCFileModuleFooter-e6rbca-1 kUUNkj" Then
elemValue = Trim(htmlEle1.innerText)
If InStr(UCase$(elemValue), "CONSTITU") > 0 Then
'Found Value
Exit For
End If
End If
Next htmlEle1
The problem is that I can't find the ClassName "styles__SCFileModuleFooter-e6rbca-1 kUUNkj", because I notice that when I manually insert the value (500004064) in the search box of the URL : https://www.informadb.pt/pt/pesquisa/, the Web Page generates addicinal traffic and turns up at an end point URL : https://www.informadb.pt/pt/pesquisa/empresa/?Duns=453060832, where that className can be found in the Request ResponseText.
My goal is to use the First URL to retrieve the Duns number '453060832', to be able to access the information in the ResponseText of the EndPoint URL. And to catch Duns Number, I need to find a way to get the Endpoint URL, or try to get The POST request response below, and get that value using JSON parser:
{'TotalResults': 1,
'NumberOfPages': 1,
'Results': [{'Duns': '453060832',
'Vat': '500004064',
'Name': 'A PANIFICADORA CENTRAL EBORENSE, S.A.',
'Address': 'BAIRRO DE NOSSA SENHORA DO CARMO,',
'Locality': 'ÉVORA',
'OfficeType': 'HeadOffice',
'FoundIn': None,
'Score': 231.72766,
'PageUrl': '/pt/pesquisa/empresa/?Duns=453060832'}]}
I'm not being able to capture what is really happening using the XMLHTTP Browser request, that seems to be the below steps:
navigate to https://www.informadb.pt/pt/pesquisa/?search=500004064
Webpage generates additional traffic
Amongst that additional traffic is an API POST XHR request which
returns search results as JSON. That request goes to
https://www.informadb.pt/Umbraco/Api/Search/Companies and includes
the 500004064 identifier amongst the arguments within the post body
Based on the API results the browser ends up at the following URI
https://www.informadb.pt/pt/pesquisa/empresa/?Duns=453060832
Can someone help me please, I have to do it using VBA.
Thanks in advance.
A small example how to POST data to your website using VBA, and how to use bare-bones string processing to extract data from the result, as outlined in my comments above.
Function GetVatId(dunsNumber As String) As String
With New MSXML2.XMLHTTP60
.open "POST", "https://www.informadb.pt/Umbraco/Api/Search/Companies", False
.setRequestHeader "Content-Type", "application/json"
.send "{""Page"":0,""PageSize"":5,""SearchTerm"":""" & dunsNumber & """,""Filters"":[{""Key"":""districtFilter"",""Name"":""Distrito"",""Values"":[]},{""Key"":""legalFormFilter"",""Name"":""Forma Jurídica"",""Values"":[]}],""Culture"":""pt""}"
If .status = 200 Then
MsgBox "Response: " & .responseText, vbInformation
GetVatId = Mid(.responseText, InStr(.responseText, """Vat"":""") + 7, 9)
Else
MsgBox "Repsonse status " & .status, vbExclamation
End If
End With
End Function
Usage:
Dim vatId As String
vatId = GetVatId("453060832") ' => "500004064"
For a more robust solution, you should use a JSON parser and -serializer, something like https://github.com/VBA-tools/VBA-JSON.

VB.NET The remote server returned an error: (405) Method Not Allowed

The below code works on some URLs, but some other URLs having parameters return the error: The remote server returned an error: (405) Method Not Allowed.
my work:
Dim objHttpWebRequest As HttpWebRequest = Nothing
Dim objHttpWebResponse As HttpWebResponse = Nothing
Dim objRequestStream As Stream = Nothing
Dim objResponseStream As Stream = Nothing
Dim objXMLReader As XmlTextReader
Try
objHttpWebRequest = WebRequest.Create(URL)
'Start HttpRequest
objHttpWebRequest.Method = "POST"
objHttpWebRequest.ContentType = "application/xml"
'Get Stream Object
objRequestStream = objHttpWebRequest.GetRequestStream()
objRequestStream.Close()
'Start HTTP Response
objHttpWebResponse = objHttpWebRequest.GetResponse()
If objHttpWebResponse.StatusCode = HttpStatusCode.OK Then
objResponseStream = objHttpWebResponse.GetResponseStream()
objXMLReader = New XmlTextReader(objResponseStream)
Dim xmldoc As XmlDocument = New XmlDocument
xmldoc.Load(objXMLReader)
XMLResponse = xmldoc
objXMLReader.Close()
End If
Is the problem in the method I am using? or the content type?
Based on the status code, the problem is in the method. Not all of the URLs might be able to respond to POST requests.
Wikipedia states
405 Method Not Allowed
A request was made of a resource using a request method not supported
by that resource; for example, using GET on a form which requires data
to be presented via POST, or using PUT on a read-only resource.

Put a VBA Class into Action

My question relates to the question: JSON import to Excel
I understand most of what this post is saying, but I don't understand how to put it together in an excel module or class module. Would someone please help me to understand how I can assemble this beast to achieve my purpose?
EDIT 29-5-14 # 7.44AM -
Here is the try which I have done so far:
Installed as ClassModule syncWebRequest
'BEGIN CLASS syncWebRequest
Private Const REQUEST_COMPLETE = 4
Private m_xmlhttp As Object
Private m_response As String
Private Sub Class_Initialize()
Set m_xmlhttp = CreateObject("Microsoft.XMLHTTP")
End Sub
Private Sub Class_Terminate()
Set m_xmlhttp = Nothing
End Sub
Property Get Response() As String
Response = m_response
End Property
Property Get Status() As Long
Status = m_xmlhttp.Status
End Property
Public Sub AjaxPost(Url As String, Optional postData As String = "")
m_xmlhttp.Open "POST", Url, False
m_xmlhttp.setRequestHeader "Content-type", "application/x-www-form-urlencoded"
m_xmlhttp.setRequestHeader "Content-length", Len(postData)
m_xmlhttp.setRequestHeader "Connection", "close"
m_xmlhttp.send (postData)
If m_xmlhttp.readyState = REQUEST_COMPLETE Then
m_response = m_xmlhttp.responseText
End If
End Sub
Public Sub AjaxGet(Url As String)
m_xmlhttp.Open "GET", Url, False
m_xmlhttp.setRequestHeader "Connection", "close"
m_xmlhttp.send
If m_xmlhttp.readyState = REQUEST_COMPLETE Then
m_response = m_xmlhttp.responseText
End If
End Sub
'END CLASS syncWebRequest
Installed as Module Test
Sub Test()
Dim request As New syncWebRequest
request.AjaxGet "http://crimson/php/SiteEnquiryAjax.php?action=aisFeed&brandCode=s&siteID=0625?format=json"
Dim json As String
json = request.Response
End Sub
I'm used to working with normal modules, but have not had to work with a class module before. I am therefore trying to understand this and translate it to meet my requirements, but forgive me if I am making it a chunkier job than one would expect.
I'm trying to query data from a local webservice that returns JSON. The webservice returns data based on an ID (e.g. 0656) in the form of:
{"total":"1","results":[{"brandName":"ABC","brandingName":"Cat","siteCategory":"Production","siteName":"Scrubbed","streetAddress":"ABC RD, SUBURB, VIC 3000","siteState":"VIC","phoneNumber":"03 0909 0909","mobileNumber":"0409 090 909","faxNumber":"03 9090 9090","applicationServer":"CAT0656ABC001","dateOpened":"1979-08-21","siteNotice":"","lastContact":"2014-05-19 04:36:31",}]}
My objective is to put this in a spreadsheet where the user can enter the sites ID (e.g. 0656) and the spreadsheet will then be able to pull and respond with data as exampled above.
EDIT 29-5-14 # 8.42AM -
Updated Module Test - my intention here was to test the parser exampled in the linked question, however when I now run the macro I receive an error. My understanding is that this may be the missing piece of what I'm trying to achieve. I have now commented out the added items to stop error occurring.
Sub Test()
Dim request As New syncWebRequest
request.AjaxGet "http://crimson/php/SiteEnquiryAjax.php?action=aisFeed&brandCode=s&siteID=0625"
Dim json As String
json = request.Response
'Set clients = parser.Parse(request.Response)
'For Each client In clients
'Name = client("Name")
'State = client("siteState")
'street = client("Address")("Street")
'suburb = client("Address")("Suburb")
'city = client("Address")("City")
'Next
End Sub
EDIT 29-5-14 # 9.40AM -
To put it another way... I want to turn this: HTTP Result of "url/SiteEnquiryAjax.php?action=aisFeed&brandCode=s&siteID=0656"
{"total":"1","results":[{"brandName":"ABC","brandingName":"Cat","siteCategory":"Production","siteName":"Scrubbed","streetAddress":"ABC RD, SUBURB, VIC 3000","siteState":"VIC","phoneNumber":"03 0909 0909","mobileNumber":"0409 090 909","faxNumber":"03 9090 9090","applicationServer":"CAT0656ABC001","dateOpened":"1979-08-21","siteNotice":"","lastContact":"2014-05-19 04:36:31",}]}
Into this: Excel Output
Without knowing the exact details of the error you are receiving, I've used vba-json before and I think you're not instantiating the parser before using it:
Dim parser As New JSONLib
Set clients = parser.parse(Request.Response)
As far as the design of the project goes, I think you've done well to separate the Request as a Class and then making the request from a Module. I ran into many similar problems accessing Salesforce from Excel and created a library that I think may help: Excel-REST. It follows a similar idea, but separates it into three classes: Client, Request, and Response. Here's an example:
Sub RetrieveJSONSimple
Dim Client As New RestClient
Dim Response As RestResponse
Set Response = Client.GetJSON("url...")
If Response.Status = Ok Then
' Response.Data is parsed json
For Each Client in Response.Data
Name = Client("Name")
State = Client("siteState")
Street = Client("Address")("Street")
Suburb = Client("Address")("Suburb")
City = Client("Address")("City")
Next Client
End If
End Sub
Sub RetrieveJSONAdvanced
Dim Client As New RestClient
Client.BaseUrl = "http://crimson/php/"
' Can also setup authentication with HTTP Basic, OAuth, and others
Dim Request As New RestRequest
Request.Resource = "SiteEnquiryAjax.php?action=aisFeed&brandCode=s&siteID={SiteId}"
Request.AddUrlSegment "SiteId", "0625"
' GET and json are default, but can be set
Request.Method = httpGET
Request.Format = json
Dim Response As RestResponse
Set Response = Client.Execute(Request)
' Process as before
End Sub

Getting multiple SQL Reports with HttpWebRequest - 401 Unauthorized

I am trying to call multiple SQL Reporting Services Reports, get the .pdfs back, then append them together. I have no problems appending .pdfs, but I'm getting an error on the second report. Here's some example code:
Dim httpReq As System.Net.HttpWebRequest = DirectCast(System.Net.WebRequest.Create(strLink), System.Net.HttpWebRequest)
Dim creds As New System.Net.NetworkCredential
creds.Domain = "MyDomain"
creds.UserName = "UserName"
creds.Password = "Password"
httpReq.Credentials = creds
Dim httpResp As System.Net.HttpWebResponse = DirectCast(httpReq.GetResponse(), System.Net.HttpWebResponse)
httpResp.Close()
httpReq = Nothing
httpResp = Nothing
Dim SecondHttpReq As System.Net.HttpWebRequest = DirectCast(System.Net.WebRequest.Create(strSecondLink), System.Net.HttpWebRequest)
SecondHttpReq.Credentials = creds
Dim SecondHttpResp As System.Net.HttpWebResponse = DirectCast(SecondHttpReq.GetResponse(), System.Net.HttpWebResponse)
When I try to create the second HttpResponse, I get a 401 Unauthorized error. When I check the SecondHttpReq object when it errors, I find that the Credentials property has been set back to Nothing. I've tried using a CookieContainer to no avail. I'd really rather not have to write a parent/sub report to get these together, so I'd like to hear other options. Thanks in advance.
Fixed. Someone changed permissions on our report server without notifying anyone.