I have written my own logging software and I would like to be able to insert a new QSO into my QRZ logbook using VB.NET (Winforms, Framework 4.8). This is my code: Imports System.Net.Http Sub PostLogEntry() Dim postString As New StringBuilder postString.Append("KEY=AAAA-BBBB-CCCC-DDDD") ' Not showing my actual key! postString.Append("&") postString.Append("ACTION=INSERT") postString.Append("&") postString.Append("ADIF=<call:5>G9ZZZ<gridsquare:6>JO00FW<mode:3>FT8<rst_sent:3>+10<rst_rcvd:3>-05<qso_date:8>20240121<time_on:6>120000") postString.Append("<qso_date_off:8>20240121<time_off:6>120100<band:2>6m<station_callsign:5>G4IJE<my_gridsquare:6>JO01HP<eor>") Using client As New HttpClient Dim endpoint = New Uri("https://logbook.qrz.com/api") Dim PostData = New StringContent(postString.ToString) Dim result = client.PostAsync(endpoint, PostData).Result.Content.ReadAsStringAsync().Result MessageBox.Show(result.ToString) End Using End Sub The result returned is STATUS=AUTH&RESULT=AUTH&REASON=invalid api key I have contacted QRZ support and they have allocated a new API Key, but it has not helped so perhaps my code is wrong. Are there any logbook developers out there using VB or C# with the QRZ API that can help me get this right? Thanks and 73, Paul G4IJE.
While not specifically addressing the api key failure there is no need to have the stringbuilder on multiple lines. Dim postString As New StringBuilder("KEY=AAAA-BBBB-CCCC-DDDD&ACTION=INSERT&ADIF=<call:5>G9ZZZ<gridsquare:6>JO00FW<mode:3>FT8<rst_sent:3>+10<rst_rcvd:3>-05<qso_date:8>20240121<time_on:6>120000<qso_date_off:8>20240121<time_off:6>120100<band:2>6m<station_callsign:5>G4IJE<my_gridsquare:6>JO01HP<eor>") The variables, for the most part are not typed. Probably getting default variants instead of the correct object type. For example, change Using client As New HttpClient to Using client As HttpClient = New HttpClient() Fix the other Dims to properly type. Dim endpoint Dim PostData Dim result For example, Dim result as HttpResponseMessage Fix the other Dims.
The StringBuilder is just to make the code more readable. It also made it easy to change the ampersand separator to a semi-colon, which is mentioned in the API spec. It didn't help though. VS 2022 prompts that "Object creation can be simplified" when using verbose definitions like "Using client As HttpClient = New HttpClient". I tried anyway of course but it still gave the same error. Thanks for your input. 73, Paul G4IJE.
My point with the stringbuilder -- there is no need for the numerous appends. Could have continued the lines with & for example Dim postString As New StringBuilder("KEY=AAAA-BBBB-CCCC-DDDD&ACTION=INSERT&ADIF=<call:5>G9ZZZ" & "<gridsquare:6>JO00FW<mode:3>FT8<rst_sent:3>+10<rst_rcvd:3>-05<qso_date:8>20240121" & "<time_on:6>120000<qso_date_off:8>20240121<time_off:6>120100<band:2>6m<station_callsign:5>" & "G4IJE<my_gridsquare:6>JO01HP<eor>") Did you properly declare the other variables?
The instructions indicate "all post data is URL encoded into a single string". Where is the URL encoding in the original posted code? https://learn.microsoft.com/en-us/d...de?view=net-8.0&redirectedfrom=MSDN#overloads
After fixing the http encoding and properly typing all dims fix the following from Dim result = client.PostAsync(endpoint, PostData).Result.Content.ReadAsStringAsync().Result to Dim result as HttpResponseMessage result = client.PostAsync(endpoint, postString.ToString).Result.Content.ReadAsStringAsync().Result
I lost track of the URL encoding somewhere along the many iterations of the code. I have seen so many different ways of doing an HTTP POST it has become something of a blur! I have tried yet another method (suggested by Google Bard) but still get the same API key error message. Here's the code anyway: Dim postString As New StringBuilder postString.Append("KEY=AAAA-BBBB-CCCC-DDDD") postString.Append("&") postString.Append("ACTION=INSERT") postString.Append("&") postString.Append("ADIF=<call:5>G9ZZZ<gridsquare:6>JO00FW<mode:3>FT8<rst_sent:3>+10<rst_rcvd:3>-05<qso_date:8>20240121<time_on:6>120000") postString.Append("<qso_date_off:8>20240121<time_off:6>120100<band:2>6m<station_callsign:5>G4IJE<my_gridsquare:6>JO01HP<eor>") Dim dataToPost As String = postString.ToString Dim encodedData As String = WebUtility.UrlEncode(dataToPost) Dim request As HttpWebRequest = CType(WebRequest.Create("https://logbook.qrz.com/api"), HttpWebRequest) request.Method = "POST" request.ContentType = "application/x-www-form-urlencoded" request.ContentLength = encodedData.Length Using stream = request.GetRequestStream() Dim bytes As Byte() = Encoding.ASCII.GetBytes(encodedData) stream.Write(bytes, 0, bytes.Length) End Using Dim response As HttpWebResponse = CType(request.GetResponse(), HttpWebResponse) Using reader As New StreamReader(response.GetResponseStream()) Dim responseText As String = reader.ReadToEnd() MsgBox(responseText) End Using I may try QRZ support again, just in case there really is an issue with my account. Thanks for your help. 73, Paul G4IJE.
Don't need the stream! Reason to use httpencoding as the text has characters giving HTML problems. For example, <, >, etc. These steps are unnecessary and unneeded. Dim dataToPost As String = postString.ToString Dim encodedData As String = WebUtility.UrlEncode(dataToPost) System.Web.HttpUtility.HtmlEncode(postString.ToString) when ready to send. No need to put into 1 string and then another string.
I have finally got something that works: Sub PostLogEntry2() Dim encodedData As String = HttpUtility.UrlEncode("KEY") & "=" & HttpUtility.UrlEncode("33BB-143B-2727-ACEA") & "&" encodedData &= HttpUtility.UrlEncode("ACTION") & "=" & HttpUtility.UrlEncode("INSERT") & "&" encodedData &= HttpUtility.UrlEncode("ADIF") & "=" & HttpUtility.UrlEncode("ADIF=<band:2>2m<mode:3>SSB<call:5>G9ZZZ<qso_date:8>20240128<station_callsign:5>G4IJE<time_on:4>1130<eor>") Dim request As HttpWebRequest = CType(WebRequest.Create("https://logbook.qrz.com/api"), HttpWebRequest) request.Method = "POST" request.ContentType = "application/x-www-form-urlencoded" request.ContentLength = encodedData.Length Using stream = request.GetRequestStream() Dim bytes As Byte() = Encoding.ASCII.GetBytes(encodedData) stream.Write(bytes, 0, bytes.Length) End Using Dim response As HttpWebResponse = CType(request.GetResponse(), HttpWebResponse) Using reader As New StreamReader(response.GetResponseStream()) Dim responseText As String = reader.ReadToEnd() MsgBox(responseText) End Using End Sub I can now tidy the code up a bit and incorporate it in my logging software. Thanks for your help and interest. 73, Paul G4IJE.
Really don't need to individually encode the string. Dim encodedData As String = HttpUtility.UrlEncode("KEY") & "=" & HttpUtility.UrlEncode("AAAA-BBBB-CCCC-DDDD") & "&" encodedData &= HttpUtility.UrlEncode("ACTION") & "=" & HttpUtility.UrlEncode("INSERT") & "&" encodedData &= HttpUtility.UrlEncode("ADIF") & "=" & HttpUtility.UrlEncode("ADIF=<band:2>2m<mode:3>SSB<call:5>G9ZZZ<qso_date:8>20240128<station_callsign:5>G4IJE<time_on:4>1130<eor>") EDIT THE POST TO REMOVE THE API KEY! Why 2 ADIF in the above? This will work Dim encodedData As String = HttpUtility.UrlEncode( "KEY=AAAA-BBBB-CCCC-DDDD&ACTION=INSERT&ADIF=<band:2>2m<mode:3>SSB<call:5>G9ZZZ<qso_date:8>20240128<station_callsign:5>G4IJE<time_on:4>1130<eor>") Remember strings are immutable. This means a new string object is created if the string is changed. This is considered as "expensive". https://forums.qrz.com/index.php?threads/using-the-logbook-api-in-vb-net-or-c.898570/#post-6779348 If a string value changes, then use the stringbuilder.
Hopefully no-one noticed my deliberate mistake ;-) My API Key has now been changed. Copy/paste error with the duplicate ADIF but it worked anyway. 73, Paul.
Paul, Unfortunately, your API key is still shown in post #12. Might need to get QRZ admin involved. Kraig