CURL POST request in VB.NET (json)
-
I've been struggling to send this CURL request in VB.NET and hope someone can help.. Here is a link to the documentation of the exact request I'm trying to send. This is the sample CURL request:
curl -u 'username:token' 'https://api.dev.name.com/v4/domains' -X POST -H 'Content-Type: application/json' --data '{"domain":{"domainName":"example.org"},"purchasePrice":12.99}'
Here is the code that I put together and tested:
Dim uri As New Uri("https://api.dev.name.com/v4/domains")
Dim myUsername As String = txtUsername.Text.Trim & ":" & txtApiKey.Text.Trim
Dim data As String = "{""domain"":{""domainName"":""example.org""},""purchasePrice"":12.99}"
Dim dataByte As Byte()request = WebRequest.Create(uri)
request.Headers.Add(HttpRequestHeader.Authorization, "Basic " & Convert.ToBase64String(Encoding.UTF8.GetBytes(myUsername)))
request.ContentType = "application/json"
request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36"
request.Method = "POST"dataByte = Encoding.UTF8.GetBytes(data)
request.GetRequestStream.Write(dataByte, 0, dataByte.Length)Dim myResp As HttpWebResponse
myResp = request.GetResponse()
Dim myreader As New System.IO.StreamReader(myResp.GetResponseStream)
WebResponse = myreader.ReadToEnd()MsgBox(WebResponse)
However, the code above always returns a (400) Bad Request. Here is another variation of pretty much the same code which I tried:
Dim myReq As HttpWebRequest
Dim myResp As HttpWebResponse
Dim myUsername As String = "username:token"myReq = HttpWebRequest.Create("https://api.dev.name.com/v4/domains")
myReq.Method = "POST"
myReq.ContentType = "application/json"
myReq.Headers.Add("Authorization", "Basic " & Convert.ToBase64String(Encoding.UTF8.GetBytes(myUsername)))Dim myData As String = "{""domain"":{""domainName"":""example.org""},""purchasePrice"":12.99}"
Dim dataBytes As Byte() = Encoding.UTF8.GetBytes(myData)
myReq.GetRequestStream.Write(dataBytes, 0, dataBytes.Length)myResp = myReq.GetResponse()
Dim myreader As New System.IO.StreamReader(myResp.GetResponseStream)
WebResponse = myreader.ReadToEnd()MsgBox(WebResponse)
But, as you can already guess, it also returns a 400 (Bad Request).
-
I've been struggling to send this CURL request in VB.NET and hope someone can help.. Here is a link to the documentation of the exact request I'm trying to send. This is the sample CURL request:
curl -u 'username:token' 'https://api.dev.name.com/v4/domains' -X POST -H 'Content-Type: application/json' --data '{"domain":{"domainName":"example.org"},"purchasePrice":12.99}'
Here is the code that I put together and tested:
Dim uri As New Uri("https://api.dev.name.com/v4/domains")
Dim myUsername As String = txtUsername.Text.Trim & ":" & txtApiKey.Text.Trim
Dim data As String = "{""domain"":{""domainName"":""example.org""},""purchasePrice"":12.99}"
Dim dataByte As Byte()request = WebRequest.Create(uri)
request.Headers.Add(HttpRequestHeader.Authorization, "Basic " & Convert.ToBase64String(Encoding.UTF8.GetBytes(myUsername)))
request.ContentType = "application/json"
request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36"
request.Method = "POST"dataByte = Encoding.UTF8.GetBytes(data)
request.GetRequestStream.Write(dataByte, 0, dataByte.Length)Dim myResp As HttpWebResponse
myResp = request.GetResponse()
Dim myreader As New System.IO.StreamReader(myResp.GetResponseStream)
WebResponse = myreader.ReadToEnd()MsgBox(WebResponse)
However, the code above always returns a (400) Bad Request. Here is another variation of pretty much the same code which I tried:
Dim myReq As HttpWebRequest
Dim myResp As HttpWebResponse
Dim myUsername As String = "username:token"myReq = HttpWebRequest.Create("https://api.dev.name.com/v4/domains")
myReq.Method = "POST"
myReq.ContentType = "application/json"
myReq.Headers.Add("Authorization", "Basic " & Convert.ToBase64String(Encoding.UTF8.GetBytes(myUsername)))Dim myData As String = "{""domain"":{""domainName"":""example.org""},""purchasePrice"":12.99}"
Dim dataBytes As Byte() = Encoding.UTF8.GetBytes(myData)
myReq.GetRequestStream.Write(dataBytes, 0, dataBytes.Length)myResp = myReq.GetResponse()
Dim myreader As New System.IO.StreamReader(myResp.GetResponseStream)
WebResponse = myreader.ReadToEnd()MsgBox(WebResponse)
But, as you can already guess, it also returns a 400 (Bad Request).
In your CURL command, you are using the '-u' option to provide the username and token as a basic authentication header. In your VB.NET code, you're attempting to encode the credentials manually. Make sure that 'myUsername' has the correct username and token values, and try using the Credentials property of the 'WebRequest' object instead of manually adding the header -
request.Credentials = New NetworkCredential(txtUsername.Text.Trim, txtApiKey.Text.Trim)
The JSON data you're sending in the CURL command needs to be properly serialized before sending it, we use Newtonsoft.Json, not sure if it will help in your situation, if so you can use it where you create an anonymous type to represent the JSON structure and then serializes it using 'JsonConvert.SerializeObject()' -
Imports Newtonsoft.Json
Dim domainData As New With {
.domain = New With {
.domainName = "example.org"
},
.purchasePrice = 12.99
}Dim data As String = JsonConvert.SerializeObject(domainData)
You need to close the request stream before sending the request -
request.GetRequestStream.Close()
Instead of directly displaying returned responses in a message box, you can return the status codes and any error messages further by using -
Dim statusCode As Integer = CType(myResp, HttpWebResponse).StatusCode
Dim responseText As String = String.EmptyIf statusCode = HttpStatusCode.OK Then
Dim myreader As New System.IO.StreamReader(myResp.GetResponseStream)
responseText = myreader.ReadToEnd()
End IfMsgBox(responseText)
I hope any of these suggestions help.
-
In your CURL command, you are using the '-u' option to provide the username and token as a basic authentication header. In your VB.NET code, you're attempting to encode the credentials manually. Make sure that 'myUsername' has the correct username and token values, and try using the Credentials property of the 'WebRequest' object instead of manually adding the header -
request.Credentials = New NetworkCredential(txtUsername.Text.Trim, txtApiKey.Text.Trim)
The JSON data you're sending in the CURL command needs to be properly serialized before sending it, we use Newtonsoft.Json, not sure if it will help in your situation, if so you can use it where you create an anonymous type to represent the JSON structure and then serializes it using 'JsonConvert.SerializeObject()' -
Imports Newtonsoft.Json
Dim domainData As New With {
.domain = New With {
.domainName = "example.org"
},
.purchasePrice = 12.99
}Dim data As String = JsonConvert.SerializeObject(domainData)
You need to close the request stream before sending the request -
request.GetRequestStream.Close()
Instead of directly displaying returned responses in a message box, you can return the status codes and any error messages further by using -
Dim statusCode As Integer = CType(myResp, HttpWebResponse).StatusCode
Dim responseText As String = String.EmptyIf statusCode = HttpStatusCode.OK Then
Dim myreader As New System.IO.StreamReader(myResp.GetResponseStream)
responseText = myreader.ReadToEnd()
End IfMsgBox(responseText)
I hope any of these suggestions help.
Hey Andre, Thanks so much for your detailed reply and explanation! I imported Newtonsoft.json no problem and tried implementing your changes. On a positive note, I'm no longer getting a (400) Bad Request reply. However, I'm now getting a (401) Unauthorized response. I've double checked my login details and made sure they were correct. I also tried testing in both the OTE (operational test environment) and the LIVE environment because the details are slightly different for each, but received the same error on both. Could this be due to how the credentials are now being passed? Also, if I close "GetRequestStream" before sending the request then I get a message the connection was suddenly terminated when trying to send the request. However, if I put it directly after writing to the stream that issue goes away. Here is a look at my updated code:
Dim uri As New Uri("https://api.dev.name.com/v4/domains")
Dim domainData As New With {
.domain = New With {
.domainName = "example.org"
},
.purchasePrice = 12.99
}Dim data As String = JsonConvert.SerializeObject(domainData)
Dim dataByte As Byte()request = WebRequest.Create(uri)
request.Credentials = New NetworkCredential(txtUsername.Text.Trim, txtApiKey.Text.Trim)
request.ContentType = "application/json"
request.Method = "POST"dataByte = Encoding.UTF8.GetBytes(data)
request.GetRequestStream.Write(dataByte, 0, dataByte.Length)
request.GetRequestStream.Close()Dim myResp As HttpWebResponse
myResp = request.GetResponse()
Dim statusCode As Integer = CType(myResp, HttpWebResponse).StatusCode
Dim responseText As String = String.EmptyIf statusCode = HttpStatusCode.OK Then
Dim myreader As New System.IO.StreamReader(myResp.GetResponseStream)
responseText = myreader.ReadToEnd()
End IfMsgBox(responseText)
Any suggestions? Thanks again!
-
Hey Andre, Thanks so much for your detailed reply and explanation! I imported Newtonsoft.json no problem and tried implementing your changes. On a positive note, I'm no longer getting a (400) Bad Request reply. However, I'm now getting a (401) Unauthorized response. I've double checked my login details and made sure they were correct. I also tried testing in both the OTE (operational test environment) and the LIVE environment because the details are slightly different for each, but received the same error on both. Could this be due to how the credentials are now being passed? Also, if I close "GetRequestStream" before sending the request then I get a message the connection was suddenly terminated when trying to send the request. However, if I put it directly after writing to the stream that issue goes away. Here is a look at my updated code:
Dim uri As New Uri("https://api.dev.name.com/v4/domains")
Dim domainData As New With {
.domain = New With {
.domainName = "example.org"
},
.purchasePrice = 12.99
}Dim data As String = JsonConvert.SerializeObject(domainData)
Dim dataByte As Byte()request = WebRequest.Create(uri)
request.Credentials = New NetworkCredential(txtUsername.Text.Trim, txtApiKey.Text.Trim)
request.ContentType = "application/json"
request.Method = "POST"dataByte = Encoding.UTF8.GetBytes(data)
request.GetRequestStream.Write(dataByte, 0, dataByte.Length)
request.GetRequestStream.Close()Dim myResp As HttpWebResponse
myResp = request.GetResponse()
Dim statusCode As Integer = CType(myResp, HttpWebResponse).StatusCode
Dim responseText As String = String.EmptyIf statusCode = HttpStatusCode.OK Then
Dim myreader As New System.IO.StreamReader(myResp.GetResponseStream)
responseText = myreader.ReadToEnd()
End IfMsgBox(responseText)
Any suggestions? Thanks again!
Closing the stream - my bad, I added it prematurely. :doh: Please disregard my suggestion to close the request stream before sending the request or add it after the stream were read. (401) Unauthorized response, it seems that your server did not accept the given credentials as valid. - There are a few things you can try. Make sure that the API you are accessing is expecting basic authentication and that the credentials should be provided in the Authorization header. If the API expects a different authentication method, such as API keys or OAuth, you will need to adjust your authentication to accept the request as per their requirements. Check that the API endpoint you are using (https://api.dev.name.com/v4/domains) is 100% correct. To isolate or debug the issue, you could try using a different client, such as cURL or Postman, with the same credentials and endpoint. This might help determine if the problem lies with the code or if there might be an issue with the credentials or API itself. Check your API documentation to make sure that you are following the correct authentication process and that there are no additional steps required. Hope this points you in the right direction.