ad: wmr-1

Using the logbook API in VB.NET (or C#)

Discussion in 'QRZ XML Logbook Data' started by G4IJE, Jan 26, 2024.

ad: L-HROutlet
ad: l-rl
ad: L-MFJ
ad: Radclub22-2
ad: Left-2
ad: abrind-2
ad: Left-3
  1. G4IJE

    G4IJE XML Subscriber QRZ Page

    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.
     
  2. KG4LAC

    KG4LAC Ham Member QRZ Page

    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.
     
  3. G4IJE

    G4IJE XML Subscriber QRZ Page

    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.
     
  4. KG4LAC

    KG4LAC Ham Member QRZ Page

    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?
     
  5. KG4LAC

    KG4LAC Ham Member QRZ Page

    Where is the QRZ api info? I want to review/analyze.
     
  6. G4IJE

    G4IJE XML Subscriber QRZ Page

  7. KG4LAC

    KG4LAC Ham Member QRZ Page

  8. KG4LAC

    KG4LAC Ham Member QRZ Page

    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
     
  9. G4IJE

    G4IJE XML Subscriber QRZ Page

    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.
     
  10. KG4LAC

    KG4LAC Ham Member QRZ Page

    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.
     
    Last edited: Jan 27, 2024
  11. KG4LAC

    KG4LAC Ham Member QRZ Page

    Paul, I'm willing to work on this item here or directly to get this working for you.
     
  12. G4IJE

    G4IJE XML Subscriber QRZ Page

    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.
     
  13. KG4LAC

    KG4LAC Ham Member QRZ Page

    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.
     
  14. G4IJE

    G4IJE XML Subscriber QRZ Page

    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.
     
  15. KG4LAC

    KG4LAC Ham Member QRZ Page

    Paul,
    Unfortunately, your API key is still shown in post #12. Might need to get QRZ admin involved.

    Kraig
     

Share This Page

ad: elecraft