I have a fully functional "app" I created in Microsoft Access that I use control my Philips Hue lights. They operate via a RESTful interface using JSON commands and it was pretty simple to create the code in VBA. I wanted to make a standalone Windows app though so I can run it on my computers that don't have Access.
I'm trying to use Visual Studio 2015 to make a universal app using VB.net but I'm having problems converting some of my code over. I was able to fix most of the glitches, but I can't get the winHttpReq commands to work. In my research, it sounds like they don't have a direct correlation in VB.net but none of the suggestions I found have worked.
Dim Result As String
Dim MyURL As String, postData As String, strQuote As String
Dim winHttpReq As Object
winHttpReq = CreateObject("WinHttp.WinHttpRequest.5.1")
'Create address and lamp
MyURL = "http://" & IP.Text & "/api/" & Hex.Text & "/lights/" & "1" & "/state"
postData = Code.Text
winHttpReq.Open("PUT", MyURL, False)
winHttpReq.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded")
winHttpReq.Send(postData)
I get the error that 'CreateObject' is not declared. It may be inaccessible due to its protection level. I'm pretty new to VB.net coding but all the recommendations for alternative posting methods don't seem to work. Any suggestions would be greatly appreciated.
In VB.Net, use WebRequest:
'Create address and lamp
MyURL = "http://" & IP.Text & "/api/" & Hex.Text & "/lights/" & "1" & "/state"
Dim request As WebRequest = WebRequest.Create(MyURL)
' Get the response.
Dim response As WebResponse = request.GetResponse()
' Display the status.
Console.WriteLine(CType(response,HttpWebResponse).StatusDescription)
' Get the stream containing content returned by the server.
Dim dataStream As Stream = response.GetResponseStream()
' Open the stream using a StreamReader for easy access.
Dim reader As New StreamReader(dataStream)
' Read the content.
Dim responseFromServer As String = reader.ReadToEnd()
' Display the content.
Console.WriteLine(responseFromServer)
' Clean up the streams and the response.
reader.Close()
response.Close()
Related
A while ago I wrote a programme in VB.NET to use the Betfair Exchange API. It has worked perfectly for months, but overnight on Tuesday it stopped working. I can still log in, but from Wednesday I have been unable to get anything else from the server.
Betfair are investigating, but according to them nobody else seems to be experiencing the same problem - although I'm not sure how many will be using VB.NET.
Below is the function I have been using to obtain data from the API. Like I said it was working on Tuesday night but not from Wednesday morning. Is there anything here which is "not perfect" or "could be better", or perhaps there is some alternative code I could try? Or is there something which might have happened on my pc which has caused the problem?
The programme falls over at the line "dataStream = request.GetRequestStream() ". The error is "Received an unexpected EOF or 0 bytes from the transport stream."
I would be grateful for any advice that anyone could offer. Thank you!
Public Function CreateRequest(ByVal postData As String, Optional ByVal accountsApi As Boolean = False)
Dim Url As String = "https://api.betfair.com/exchange/betting/json-rpc/v1"
If accountsApi Then Url = "https://api.betfair.com/exchange/account/json-rpc/v1"
Dim request As WebRequest = Nothing
Dim dataStream As Stream = Nothing
Dim response As WebResponse = Nothing
Dim strResponseStatus As String = ""
Dim reader As StreamReader = Nothing
Dim responseFromServer As String = ""
Try
request = WebRequest.Create(New Uri(Url))
request.Method = "POST"
request.ContentType = "application/json-rpc"
request.Headers.Add(HttpRequestHeader.AcceptCharset, "ISO-8859-1,utf-8")
request.Headers.Add("X-Application", appKey)
request.Headers.Add("X-Authentication", sessToken)
Dim byteArray As Byte() = Encoding.UTF8.GetBytes(postData) ' Data to post such as ListEvents, ListMarketCatalogue etc
request.ContentLength = byteArray.Length ' Set the ContentLength property of the WebRequest.
dataStream = request.GetRequestStream() ' Get the request stream.
dataStream.Write(byteArray, 0, byteArray.Length) ' Write the data to the request stream.
dataStream.Close() ' Close the Stream object.
response = request.GetResponse() ' Get the response.
strResponseStatus = CType(response, HttpWebResponse).StatusDescription ' Display the status below if required
dataStream = response.GetResponseStream() ' Get the stream containing content returned by the server.
reader = New StreamReader(dataStream) ' Open the stream using a StreamReader for easy access.
responseFromServer = reader.ReadToEnd() ' Read the content.
reader.Close() : dataStream.Close() : response.Close()
Catch ex As Exception
MsgBox("CreateRequest Error" & vbCrLf & ex.Message, MsgBoxStyle.Critical, " Error")
End Try
Return responseFromServer
End Function
I would check that the provider hasn't recently deprecated use of TLS 1.0 (as they should have done before now, in fact).
If so, your code needs to enforce use of TLS 1.1+:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
This only has to be set once, usually in the (static) type initializer or similar.
And I 100% agree with Andrew Mortimer that you should use Using blocks wherever possible. I'd also suggest moving all of your string values into variables or constants to clean things up and keep them maintainable. Eg:
Const ContentType As String = "application/json-rpc"
...
request.ContentType = ContentType
UPDATE
I just found this announcement on their site:
https://forum.developer.betfair.com/forum/developer-program/announcements/33563-tls-1-0-no-longer-supported-from-1st-december-all-betfair-api-endpoints
If you are allowed to use external dependencies within this project I would recommend using RestSharp nuget package it works really well for creating API requests and getting there response without having to use httpclient which gets messy.
Link: https://restsharp.dev/
I have a problem with my FTP upload and I hope you can help me. I'm trying create folders and then upload files to them. What my program should do is checking if a folder already exists, and if not, create a new one with the name checked before. The program runs fine, except for the error described below.
My Problem:
I want to upload a folder called ghandle -> works as intended.
After that, I want to upload a folder called handle -> doesn't work, because the .Contains method that checks the folders on the FTP server, finds ghandle and stops, because ghandle contains handle.
Are there other options like .Contains which will just check for whole words or exact matches?
Here is my source code:
Dim dirname = Path.GetFileNameWithoutExtension(openFileDialogHtml.FileName) & "_files"
Dim ftp = "ftp://" & ftp_address.Text & "/"
Dim user = ftp_user.Text
Dim pass = ftp_password.Text
Dim request As Net.FtpWebRequest = Net.FtpWebRequest.Create(ftp)
Dim creds As Net.NetworkCredential = New Net.NetworkCredential(user, pass)
request.Credentials = creds
Dim resp As Net.FtpWebResponse = Nothing
request.Method = Net.WebRequestMethods.Ftp.ListDirectoryDetails
request.KeepAlive = True
Using resp
resp = request.GetResponse()
Dim sr As StreamReader = New StreamReader(resp.GetResponseStream(), System.Text.Encoding.ASCII)
Dim s As String = sr.ReadToEnd()
If Not s.Contains(dirname) Then
request = Net.FtpWebRequest.Create(ftp & dirname)
request.Credentials = creds
request.Method = Net.WebRequestMethods.Ftp.MakeDirectory
resp = request.GetResponse()
MsgBox("Created folder " & dirname)
Else
MsgBox("Folder " & dirname & " already exists!")
End If
End Using
Thanks in advance
First, use ListDirectory, not ListDirectoryDetails. The ListDirectory returns plain names only, what is enough for your purpose and easy to parse.
Then just split the output to an array of individual file names, using the String.Split method:
Dim names As String() =
sr.ReadToEnd().Split(
New Char() {vbCr, vbLf}, StringSplitOptions.RemoveEmptyEntries)
And use the IEnumerable.Contains extension method to check for given file name:
If Not names.Contains(dirname) Then
I'm using vb 2010 to communicate with an Classic ASP page. I'm trying to write a routine that checks the validity of the program using StreamReader, WebRequest and WebResponse
Dim inStream As StreamReader
Dim webRequest As WebRequest
Dim webResponse As WebResponse
Dim encode As Encoding = System.Text.Encoding.GetEncoding("utf-8")
Dim sURL As String = "http://localhost/activate-check.asp?"
webRequest = webRequest.Create(sURL & "key=" & sFullKey & "email=" & txtEmail.Text)
webResponse = webRequest.GetResponse()
inStream = New StreamReader(webResponse.GetResponseStream, encode)
Dim sResponse As String = inStream.ReadToEnd()
The code works perfectly, but the url data is in plain text and so is the reply
http://localhost/activate-check.asp?key=1234567890&email=email#email.com
Is there a way that the request data can be encrypted and then decrypted on the asp page
There are many valid use cases for encryption; URL parameters is not one of them.
If you disagree with this recommendation, make sure you're at least using authenticated encryption, unless you like weird exploits from chosen-ciphertext attacks.
i currently have this code as my FTP code (Which works a charm!)
Using ms As New System.IO.MemoryStream
test.Image.Save(ms, System.Drawing.Imaging.ImageFormat.Png)
Using wc As New System.Net.WebClient
wc.UploadData("ftp://" & My.Settings.username & ":" & My.Settings.password & "#ftp." & My.Settings.server & My.Settings.imagelocation & filename & ".jpg", ms.ToArray())
End Using
End Using
however i have a new username and directory etc, and they contain "#" this is my username for example: "snap#example.com"
but my username before would be for instance "test" you see without the "#" im guessing its because it messes with the "#ftp" part, Any suggestions how to fix?
Short answer:
Encode your username and password using System.Web.HttpUtility.UrlPathEncode before creating your URL.
Long answer:
According to the IETF's RFC 1738, which is a standards track document about URLs, it explicitly says
Within the user and password field, any ":", "#", or "/" must be encoded.
The actual URL spec document does not explicitly mention encoding special characters in usernames and passwords, but I think it's implied that you can encode them. And it says
Because a % sign always indicates
an encoded character, a URL may be made safer simply by encoding
any characters considered unsafe, while leaving already encoded.
So you should percent-escape any special charaters in your URL, and in the case of an '#' that's %40.
Alternatively you could use the following classes provided by .net:
FtpWebRequest
WebRequestMethods
NetworkCredential
Private Shared Sub UploadFileToFTP(source As String)
Try
Dim filename As String = Path.GetFileName(source)
Dim ftpfullpath As String = ftpurl
Dim ftp As FtpWebRequest = DirectCast(FtpWebRequest.Create(ftpfullpath), FtpWebRequest)
ftp.Credentials = New NetworkCredential(ftpusername, ftppassword)
ftp.KeepAlive = True
ftp.UseBinary = True
ftp.Method = WebRequestMethods.Ftp.UploadFile
Dim fs As FileStream = File.OpenRead(source)
Dim buffer As Byte() = New Byte(fs.Length - 1) {}
fs.Read(buffer, 0, buffer.Length)
fs.Close()
Dim ftpstream As Stream = ftp.GetRequestStream()
ftpstream.Write(buffer, 0, buffer.Length)
ftpstream.Close()
Catch ex As Exception
Throw ex
End Try
End Sub
I'm using vb.net window based and I want to get or download the FileImage in my SQL server. In ASP.NET I can download it via this code. But I want to translate it to windows based. Can you help me please?
Thanks,
Dim oFileType As String = oPortal.GetDs("FileType")
Dim oFile As Byte() = oPortal.GetDs("FileImage")
Dim oRecordKey As String = oPortal.GetDs("FileName")
Response.ContentType = "image/" & oFileType
If Request.QueryString("open") <> "" Then
Response.AppendHeader("Content-Disposition", "attachment; filename=" & oRecordKey)
End If
Response.BinaryWrite(oFile)
Response.End()
Got it. File.WriteAllBytes(oPath & oFileName, WebCtrl.GetDs("FileImage"))