HttpWebRequest and Response Issues - vb.net

So i have this class that I use for HTTPwebrequests. In this instance of my program I'm posting some data as well as a cookie. Now heres the really wierd part. I use fiddler to sniff headers and monitor the traffic of my program in testing. If fiddler is open this function works just fine. If fidler is closed whenever I go to post anydata the operation times out. It always does this. No matter what I do. Can any one shed some light on this as I'm pulling my hair out in frustration.
Public Function Send(ByVal URL As String, _
Optional ByVal PostData As String = "", _
Optional ByVal Method As HTTPMethod = HTTPMethod.HTTP_GET, _
Optional ByVal ContentType As String = "", Optional ByVal Refer As String = "")
Dim Request As HttpWebRequest = WebRequest.Create(URL)
Dim Response As HttpWebResponse
System.Net.ServicePointManager.Expect100Continue = False
Dim SW As StreamWriter
Dim SR As StreamReader
Dim ResponseData As String
Dim a As New CookieContainer()
' Request.Proxy = New WebProxy("173.234.250.164", 3128)
' Prepare Request Object
Request.Method = Method.ToString().Substring(5)
Request.CookieContainer = a
' Set form/post content-type if necessary
If (Method = HTTPMethod.HTTP_POST AndAlso PostData <> "" AndAlso ContentType = "") Then
ContentType = "application/x-www-form-urlencoded"
End If
'Set User Agent
Request.UserAgent = ("Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; GTB6.6)")
'Set Refer
If (Refer <> "") Then
Request.Referer = Refer
End If
' Set Content-Type
If (ContentType <> "") Then
Request.ContentType = ContentType
Request.ContentLength = PostData.Length
End If
'Set Cookie If Given
If (Cookie <> "") Then
Request.Headers.Add("cookie", Cookie)
End If
' Send Request, If Request
If (Method = HTTPMethod.HTTP_POST) Then
Try
Debug.Print("Inside Post")
SW = New StreamWriter(Request.GetRequestStream())
SW.Write(PostData)
Debug.Print("Wrote Post Data")
Catch Ex As Exception
Throw Ex
Finally
SW.Close()
End Try
End If
' Receive Response
Try
Response = Request.GetResponse()
For Each cook As Cookie In Response.Cookies
Cookie = Cookie & cook.ToString() & ";"
Next
Debug.Print(Cookie)
SR = New StreamReader(Response.GetResponseStream())
ResponseData = SR.ReadToEnd()
Catch Wex As System.Net.WebException
SR = New StreamReader(Wex.Response.GetResponseStream())
ResponseData = SR.ReadToEnd()
Throw New Exception(ResponseData)
Finally
SR.Close()
End Try
Return ResponseData
End Function

You're never disposing the HttpWebResponse - which means the connection is going to be held open. You should use a Using statement for Response. (I'd also suggest that you declare variables as late as possible, rather than declaring everything at the top of the method... and that you use Using statements everywhere instead of closing things in Finally blocks.
Note that you're also closing SR in a finally block when it may not be set - if some exception you weren't expecting is thrown, your attempt to close SR may throw a NullReferenceException. Personally I'd treat the two StreamReaders (one in the success case and one in the failure case) separately.

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"

Google OAuth Token error - 400 Bad Request

I'm trying to authenticate my application using OAuth2 and using the 'installed applications' flow (get auth-code and then request token). I'm getting a 400 bad request error when requesting the token on the GetResponse() line. My code is as follows:
Public Sub New()
Dim tokenRequest As WebRequest =
WebRequest.Create("https://accounts.google.com/o/oauth2/token")
Dim requestString As String = "code=<auth-code>" _
& "&client_id=<client_id>" _
& "&client_secret=<client_secret>" _
& "&redirect_uri=http://localhost" _
& "&grant_type=authorization_code"
byteArray = StrToByteArray(System.Web.HttpUtility.UrlEncode(requestString))
tokenRequest.Credentials = CredentialCache.DefaultCredentials
tokenRequest.Method = "POST"
tokenRequest.ContentLength = byteArray.Length
tokenRequest.ContentType = "application/x-www-form-urlencoded"
Dim dataStream As Stream = tokenRequest.GetRequestStream()
dataStream.Write(byteArray, 0, byteArray.Length)
dataStream.Close()
Console.WriteLine("Getting response...")
'Get response
Try
Dim response As WebResponse = tokenRequest.GetResponse()
Console.WriteLine(CType(response, HttpWebResponse).StatusDescription)
Dim data As Stream = response.GetResponseStream
Array.Resize(byteArray, 4096)
Array.Clear(byteArray, 0, byteArray.Length)
data.Read(byteArray, 0, byteArray.Length)
response.Close()
Catch wex As WebException
Console.WriteLine("ERROR! : ")
Console.WriteLine(wex.Message)
Console.WriteLine(wex.Status)
Console.WriteLine(wex.Data)
Console.WriteLine(wex.InnerException.Message)
Console.WriteLine(wex.HelpLink)
End Try
End Sub
The specifics of the error are below:
The remote server returned an error: (400) Bad Request.
7
System.Collections.ListDictionaryInternal
System.NullReferenceException: Object reference not set to an instance of an obj
ect.
at GADownload.GoogleAnalytics..ctor() in ***.vb:line 86
at GADownload.Main1.Main(String[] args) in ****.vb:line 18
I've had a look at Google GetAccessToken : Bad Request 400 and Google GData .Net OAuthUtil.GetAccessToken 400 Bad Request but have not found a solution suited to this code. I have already checked all the solutions suggested and implemented them, but with no luck so far.
looks like you are not setting values for the parameters auth-code, client_id or client_secret.
you can debug these parameters with a curl command to see if this is the source of the problem. e.g.
curl -X POST -d "code=<auth-code>&client_id=<client_id>&client_secret=<client_secret>"&grant_type=authorization_code" http://localhost:8000/auth/token
Can you try URL encoding redirect_uri
redirect_uri=http://localhost
That is the only thing I'm seeing on your code vs. mine. Here's my code that is similar in vb and working
Dim sb As New StringBuilder
sb.Append("code=").Append(Request.QueryString("code")) _
.Append("&client_id=") _
.Append(Session.Item("ClientID")) _
.Append("&client_secret=") _
.Append(Session.Item("ClientSecret")) _
.Append("&redirect_uri=") _
.Append(HttpUtility.UrlEncode("http://localhost/1.aspx")) _
.Append("&grant_type=authorization_code")
Dim requestGoogle As HttpWebRequest =
WebRequest.Create("https://accounts.google.com/o/oauth2/token")
requestGoogle.Method = "POST"
requestGoogle.ContentType = "application/x-www-form-urlencoded"
requestGoogle.ContentLength = sb.Length
Dim byteArray As Byte() = Encoding.UTF8.GetBytes(sb.ToString)
sb.Clear()
requestGoogle.GetRequestStream.Write(byteArray, 0, byteArray.Length)
byteArray = Nothing
Dim responseGoogle As HttpWebResponse = requestGoogle.GetResponse()
If responseGoogle.StatusCode = HttpStatusCode.OK Then
Dim sr As StreamReader = _
New StreamReader(responseGoogle.GetResponseStream)
Dim s As String = sr.ReadToEnd
sr.Close()
responseGoogle.GetResponseStream.Close()
requestGoogle.GetRequestStream.Close()
'Response.Write(s)
End If

VB.NET - Checking FTP directory exists always returns true

Can anybody tell me why the function below always returns true, even if the FTP directory in question does not exist?
The value of directoryURL which I pass in is of the form:
ftp://ip_address/directory/subdirectory/
and has a trailing forward slash.
Public Function DoesDirectoryExist(directoryUrl As String) As Boolean
' Check that the target URL is properly formatted
If Not directoryUrl.StartsWith("ftp://") Then directoryUrl = "ftp://" & directoryUrl
' Create a web request
Dim request As FtpWebRequest = DirectCast(WebRequest.Create(directoryUrl), FtpWebRequest)
request.Credentials = New NetworkCredential(_userName, _password)
request.Method = WebRequestMethods.Ftp.ListDirectory
' Try and list the contents of the directory
Try
Using response As FtpWebResponse = DirectCast(request.GetResponse(), FtpWebResponse)
' We have been succesful so the directory exists
Return True
End Using
Catch ex As WebException
Dim response As FtpWebResponse = DirectCast(ex.Response, FtpWebResponse)
If response.StatusCode = FtpStatusCode.ActionNotTakenFileUnavailable Then
Return False
Else
Throw New ApplicationException("Unable to determine if FTP directory exists.")
End If
End Try
End Function
Weird. This works for me (I don't cast the request but I guess that shouldn't matter). This is the code I usually rely on:
Dim response As FtpWebResponse = request.GetResponse()
Using (response)
found = True
End Using
The alternative you have is reading the list of directories:
Using sr As New System.IO.StreamReader(response.GetResponseStream())
Using sw As New System.IO.StreamWriter("tempfile", False)
sw.Write(sr.ReadToEnd())
End Using
End Using
In the worst scenario, it should help you to tackle the problem (e.g., it always founds a directory called "ghost", which you might use to trigger the not-found).
Method 1
Public Function DirectoryExists(directory As String) As Boolean
Dim directoryExists__1 As Boolean
Dim request = DirectCast(WebRequest.Create(directory), FtpWebRequest)
request.Method = WebRequestMethods.Ftp.ListDirectory
request.Credentials = New NetworkCredential("user", "pass")
Try
Using request.GetResponse()
directoryExists__1 = True
End Using
Catch generatedExceptionName As WebException
directoryExists__1 = False
End Try
Return directoryExists__1
End Function
Method 2
If Not DirectoryExists("ftp://" + FTPSettings.IP + "/" + lo_ScreenShotPath) Then
reqFTP = DirectCast(FtpWebRequest.Create(New Uri("ftp://" + FTPSettings.IP + "/" + lo_ScreenShotPath)), FtpWebRequest)
End If
i hope may i help this...

VB.NET Function As String, Will Return False Be A Boolean?

I have a HTTP class that gets content from URL's, POST's content to URL's etc and then returns the raw HTML content.
In the function inside of the class it detects if there is a HTTP error and if so I would like to return false but will this work if I have declared the function to return a String?
Code Sample of what I am trying to do (Note the Return Content & Return False if a HTTP error code is detected)
Public Function Get_URL(ByVal URL As String) As String
Dim Content As String = Nothing
Try
Dim request As Net.HttpWebRequest = Net.WebRequest.Create(URL)
' Request Settings
request.Method = "GET"
request.KeepAlive = True
request.AllowAutoRedirect = True
request.Timeout = MaxTimeout
request.CookieContainer = cookies
request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.60 Safari/534.24"
request.Timeout = 60000
request.AllowAutoRedirect = True
Dim response As Net.HttpWebResponse = request.GetResponse()
If response.StatusCode = Net.HttpStatusCode.OK Then
Dim responseStream As IO.StreamReader = New IO.StreamReader(response.GetResponseStream())
Content = responseStream.ReadToEnd()
End If
response.Close()
Catch e As Exception
HTTPError = e.Message
Return False
End Try
Return Content
End Function
And usage example:
Dim Content As String = Get_URL("http://www.google.com/")
If Content = False Then
MessageBox.Show("A HTTP Error Occured: " & MyBase.HTTPError)
Exit Sub
End If
Usually in this type of scenario, you would throw a new exception with more detailed information, and let the exception bubble up to the processed by the main code (or just let the original exception bubble up without Catching it in the first place).
Catch e As Exception
' wrap the exception with more info as a nested exception
Throw New Exception("Error occurred while reading '" + URL + "': " + e.Message, e)
End Try
Inside the usage example:
Dim content As String = ""
Try
content = Get_URL("http://www.google.com/")
Catch e As Exception
MessageBox.Show(e.Message)
Exit Sub
End Try