How to get result from failing webclient.downloadstring? - vb.net

If we use webclient.downloadstring on a server with error, we got nothing
Try
result = webClient.DownloadString("https://api.bodis.com/domainclassification?domain=" + CurrentBlog.Domain)
Catch ex As Exception
System.Windows.Forms.Application.DoEvents()
End Try
Usually result contains the response. But in case of error result is empty.
I want to know something. For example, even if the result is bad, usually there is a custom 404 message, etc.
The api.bodis.com is problematic because it mix secure and non secure stuff. However, it gives output anyway in internet explorer. I want to use webclient and I want to know the ouput
Getting ex.response yields nothing
Dim adult = webClient.DownloadString("http://googleads.g.doubleclick.net/apps/domainpark/domainpark.cgi?callback=_google_json_callback&output=js&client=ca-dp-godaddy2_xml&domain_name=" + CurrentBlog.Domain)
'ias.NavigateTillComplete("https://api.bodis.com/domainclassification?domain=" + CurrentBlog.Domain)
Dim result = ""
Dim url = "http://api.bodis.com/domainclassification?domain=" + CurrentBlog.Domain
Dim webRequest = DirectCast(System.Net.HttpWebRequest.Create(url), System.Net.HttpWebRequest)
Dim response As HttpWebResponse
Try
response = DirectCast(webRequest.GetResponse(), HttpWebResponse)
Catch ex As System.Net.WebException
System.Windows.Forms.Application.DoEvents()
response = DirectCast(ex.Response, HttpWebResponse) 'is nothing there
End Try
Dim responseStream = response.GetResponseStream

Related

VB.NET ~ PUT WebRequest raising exceptions when trying to GetResponse of it

I am getting TWO exceptions. The first one in the regular code and the second into the exception handling block.
I have this function (below) that supposed to change user settings in a Web API using PUT method. Everything runs fine until the point that I try to get a response from the web request. Then it raises the first exception (unknown) and when I try to handle the error I get a second exception "Object reference not set to an instance of an object".
As far as I know normally what will cause this error is the attempt of getting a response of an unassigned web request, but in this case it IS assigned and the Uri is valid. All the credentials for authorization are correct too.
This is my code:
Try
Dim webRequest As System.Net.HttpWebRequest
webRequest = System.Net.HttpWebRequest.Create(InternalSettings.APIurl + "/config")
webRequest.Headers("Authorization") = InternalSettings.APIpwd
webRequest.Headers("API-Application-Key") = InternalSettings.APIkey
webRequest.Method = "PUT"
webRequest.ContentType = "application/x-www-form-urlencoded"
Dim postData As String = ""
postData += "SaveAllCustomersData=false"
Dim byteArray As Byte() = Encoding.UTF8.GetBytes(postData)
Dim dataStream As Stream = webRequest.GetRequestStream()
dataStream.Write(byteArray, 0, byteArray.Length)
dataStream.Close()
'The next line will raise an unknown exception
Dim myHttpWebResponse As HttpWebResponse = webRequest.GetResponse
Dim responseReader As StreamReader = New StreamReader(myHttpWebResponse.GetResponseStream())
Dim responseData As String = responseReader.ReadToEnd()
responseReader.Close()
webRequest.GetResponse().Close()
Catch ex As WebException
'The next line will raise a "Object reference not set to an instance of an object" exception
Dim resp = New StreamReader(ex.Response.GetResponseStream()).ReadToEnd()
Dim obj = JsonConvert.DeserializeObject(resp)
Return False
End Try
If you are using basic authentification you can try something like this:
Dim strUrl As String = InternalSettings.APIurl + "/config"
Dim request As WebRequest = DirectCast(WebRequest.Create(strUrl), HttpWebRequest)
Dim strResponse As String = ""
Dim byteAuth() As Byte = Encoding.UTF8.GetBytes(InternalSettings.APIkey & ":" & InternalSettings.APIpwd)
Dim strPost As String = "SaveAllCustomersData=false"
Dim bytePost() As Byte = Encoding.UTF8.GetBytes(strPost)
request.ContentType = "application/x-www-form-urlencoded"
request.Method = "PUT"
request.Headers.Add("Authorization", "Basic " & Convert.ToBase64String(byteAuth))
Using sw = New StreamWriter(request.GetRequestStream())
sw.Write(bytePost, 0, bytePost.Length)
sw.Flush()
Using response As HttpWebResponse = request.GetResponse()
Using sr = New StreamReader(response.GetResponseStream())
strResponse = sr.ReadToEnd()
End Using
End Using
End Using

Send a POST request with vb.net gives 400 bad request error

I am not familiar a lot with Vb.Net, but I try to tweak something on an existent project. I have a cURL that try to implement on Vb.Net. I found different answers here and in other forums, but this way is the one I managed to reach
Private Function SendRequest(uri As Uri, jsonDataBytes As Byte(), contentType As String, method As String) As String
Dim req As WebRequest = WebRequest.Create(uri)
req.ContentType = contentType
req.Method = method
req.ContentLength = jsonDataBytes.Length
Dim stream = req.GetRequestStream()
stream.Write(jsonDataBytes, 0, jsonDataBytes.Length)
stream.Close()
Dim response = req.GetResponse().GetResponseStream()
Dim reader As New IO.StreamReader(response)
Dim res = reader.ReadToEnd()
reader.Close()
response.Close()
Return res
End Function
Dim postData As String = String.Format("text={0}", title)
Dim data = Encoding.UTF8.GetBytes(postData)
Dim uri = New Uri("https://.....")
Dim slackResponse = SendRequest(uri, data, "application/json", "POST")
And this is the error I get:
Exception Details: System.Net.WebException: The remote server returned an error: (400) Bad Request.
If I comment out the SendRequest function, I got an error during calling that, so I guess it is on that part.
Not able to debug more. Any ideas?
In order to debug more, you need to catch the WebException. WebExceptions have a response object that may contain more information.
Dim response as WebResponse
Try
response = req.GetResponse().GetResponseStream()
Catch ex As Net.WebException
If ex.Response IsNot Nothing Then
response = ex.Response
End If
End Try
This could be a problem with your URL parameters but many sites also return this class of error when there is a problem in the json content of the request.
I solved this long time ago by adding.
request.ContentType = "application/x-www-form-urlencoded"

Taking Json from API and iterating over the results

So I feel stupid for asking probably a easy question but I'm not very familiar with .NET and I've been googling for a while now.
I'm looking to take in data from a web API and be able to iterate over it. The data looks like this
[
{"id":"5", "date":"01-01-2014"},
{"id":"90", "date":"05-01-2013"}
]
What I've got so far:
Private Sub newGetData()
Dim request As HttpWebRequest
Dim response As HttpWebResponse = Nothing
Dim reader As StreamReader
Try
request = DirectCast(WebRequest.Create("http://somesite.com"), HttpWebRequest)
response = DirectCast(request.GetResponse(), HttpWebResponse)
reader = New StreamReader(response.GetResponseStream())
Dim rawresp As String
rawresp = reader.ReadToEnd()
Dim jResults As JObject = JObject.Parse(rawresp)
Dim results As List(Of JToken) = jResults.Children().ToList
For Each item As JProperty In results
item.CreateReader()
MsgBox(item.name)
Next
'usernameTextbox.text = jResults("name").ToString()
'placenameTextbox.text = jResults("place")("name").ToString()
Catch ex As Exception
MsgBox(ex.ToString)
Finally
If Not response Is Nothing Then response.Close()
End Try
End Sub
I've tried a bunch of things but it always fails on the loop. How do I go about doing this?
EDIT: The error message for this one
Newtonsoft.Json.JsonReaderException: Error reading JObject from JsonReader. Current JsonReader item is not an object: StartArray. Path '', line 1, position 1.
at Newtonsoft.Json.Linq.JObject.Load(JsonReader reader)
at Newtonsoft.Json.Linq.JObject.Parse(String json)
at Forecasting.Form1.newGetData() in

Better way to handle errors with HTTP request/response

I am new to VB...I am using the following code to make an HTTP request and buffer the response into a String:
Try
myHttpWebRequest = CType(WebRequest.Create(strUrl), HttpWebRequest)
myHttpWebResponse = CType(myHttpWebRequest.GetResponse(), HttpWebResponse)
receiveStream = myHttpWebResponse.GetResponseStream()
encode = System.Text.Encoding.GetEncoding("utf-8")
sr = New StreamReader(receiveStream, encode)
Do Until sr.Peek = -1
strLine = String.Concat(strLine, sr.ReadLine)
arrBuff.Add(strLine)
Loop
Catch ex As System.Net.WebException
MsgBox(ex.Message)
Finally
myHttpWebResponse.Close()
End Try
sr.Close()
This works fine, but errors are not handled well, for example if the request triggers a 500 response the VB code encounters an unhandled exception. Any thoughts on how to make this code better?
Use the HttpWebResponse.StatusCode to determine if the server has sent you anything but a (probably) 200 (OK).
Instead of using a MsgBox, raise an exception as follows:
Catch ex As Exception
Throw New Exception(ex.Message)
If you are making an AJAX call from a web page, you can retrieve the message by using:
Catch ex As Exception
HttpContext.Current.Response.Write(ex.Message);
HttpContext.Current.Response.StatusCode = 500;

How can I read the response from a web request when the Status is not 200?

I am having difficulty getting the response text from a HTTP web request in vb.net when I get a web exception.
This is the code I am doing it with.
Try
myWebResponse = CType(request.GetResponse(), HttpWebResponse)
myStreamReader = New StreamReader(myWebResponse.GetResponseStream())
ResponseText = myStreamReader.ReadToEnd
If myWebResponse.StatusCode = HttpStatusCode.Accepted Or myWebResponse.StatusCode = 200 Then
SendResult = True 'Sent
SendStatus = 1 'message sent successfully
Try
Integer.TryParse(myWebResponse.Headers("Number-Of-MT-PDU"), num_MT_PDU)
Catch ex As Exception
End Try
Else
SendStatus = 2 'message processed but not sent successfully
End If
Catch e As WebException
If (e.Status = WebExceptionStatus.ProtocolError) Then
Dim response As WebResponse = e.Response
Using (response)
Dim httpResponse As HttpWebResponse = CType(response, HttpWebResponse)
statusCode = httpResponse.StatusCode
Try
myStreamReader = New StreamReader(response.GetResponseStream())
Using (myStreamReader)
ResponseText = myStreamReader.ReadToEnd & "Status Description = " & HttpWebResponse.StatusDescription
End Using
Catch ex As Exception
Logger.LogError(Me, ex)
End Try
End Using
Annoyingly, the API I am contacting uses a 404 as a valid response. If I put the request in a browser some message text will be displayed. I want to be able to use that text in my program. I can not simply use the error code to determine actions as I don't think I can differentiate between a valid 404 response and an actual error.
In the code this line
myWebResponse = CType(request.GetResponse(), HttpWebResponse)
throws an exception.
In the exception I can get the 404 code and the description but not the response stream. It is always null.
If I get a 200 response I get the text in the Response stream no problem.
In the web exception response object (in Visual Studios debugger) I have checked the headers and the object values and can't find the response text anywhere. If I stick the request URL in a browser I get response text back even though it is a 404.
The raw response in fiddler:
HTTP/1.1 404 Not Found Connection: close Content-Type: text/plain; charset=UTF-8 Content-Length: 35 "The response Message"
Any ideas on how I can get "The response Message" in my program? I have to use .Net on the server.
Thanks for any help anybody can give.
This LINQPad query works fine, dumping the HTML provided by my web server's "Not Found" error web page:
Dim rq = System.Net.WebRequest.Create(New Uri("http://localhost/test"))
Try
Dim rs = rq.GetResponse
rs.Dump
Catch Ex As System.Net.WebException
Dim rs = Ex.Response
Call (New StreamReader(rs.GetResponseStream)).ReadToEnd.Dump
End Try
FYI Your code works for me, except the presumed typo re HttpWebResponse.StatusDescription (and commenting out "unrelated stuff"), again as a LINQPad query (in .NET 4.0):
Dim request = WebRequest.Create("http://localhost/test")
Dim myStreamReader As StreamReader
Dim SendStatus As Integer = -1
Dim statusCode As HttpStatusCode
Dim ResponseText As String
Try
Dim myWebResponse = CType(request.GetResponse(), HttpWebResponse)
myStreamReader = New StreamReader(myWebResponse.GetResponseStream())
ResponseText = myStreamReader.ReadToEnd
If myWebResponse.StatusCode = HttpStatusCode.Accepted Or myWebResponse.StatusCode = 200 Then
'SendResult = True 'Sent
SendStatus = 1 'message sent successfully
'Try
' Integer.TryParse(myWebResponse.Headers("Number-Of-MT-PDU"), num_MT_PDU)
'Catch ex As Exception
'End Try
Else
SendStatus = 2 'message processed but not sent successfully
End If
Catch e As WebException
If (e.Status = WebExceptionStatus.ProtocolError) Then
Dim response As WebResponse = e.Response
Using (response)
Dim httpResponse As HttpWebResponse = CType(response, HttpWebResponse)
statusCode = httpResponse.StatusCode
Try
myStreamReader = New StreamReader(response.GetResponseStream())
Using (myStreamReader)
ResponseText = myStreamReader.ReadToEnd & "Status Description = " & httpResponse.StatusDescription ' HttpWebResponse.StatusDescription
End Using
Catch ex As Exception
'Logger.LogError(Me, ex)
ex.Dump("Exception")
End Try
End Using
End If
End Try
ResponseText.Dump("ResponseText")
I have also confirmed the above code (with the inferred As clauses added and converting the .Dump calls to Console.WriteLine) works in .NET 2.0 with VB8.
Note that the key is that even though the act of GetResponseStream() throws a .NET WebException, the HttpWebResponse is actually passed to the WebException object, so when in the Catch, you do a new GetResponseStream() on the WebException.Response object.
Below, very similar code for when in the Catch of the initial GetResponseStream()
Try
OriginalResponseStream = GetResponseStream(OriginalHTTPWebResponse)
Catch wex as WebException
Dim response As WebResponse = wex.Response
Dim statusCode As HttpStatusCode
Dim ResponseText As String
Dim httpResponse As HttpWebResponse = CType(response, HttpWebResponse)
statusCode = httpResponse.StatusCode
Try
Dim myStreamReader As New StreamReader(response.GetResponseStream())
Using (myStreamReader)
ResponseText = myStreamReader.ReadToEnd
Process(ResponseText) '<===as in whatever you need to do with the response
End Using
Catch ex As Exception
HandleIt(ex.Message) '<===as in whatever you want to do if Exception during the above
End Try
End Try