Search code examples
vb.netebay-api

Ebay API GetSuggestedCategories Call Returning No categories


I seem to be having an issue with a few API calls including the GetSuggestedCategories and UploadSiteHostedPictures calls. I will focus on the GetSuggestedCategories call here as both are returning successful, but with empty values where expected.

I would love if anyone can review my code and point me in the right direction in determining what is causing the returns to be null. I have spent several days trying to determine this with no luck.

For the GetSuggestedCategories call, my code looks as follows:

Public Function GetSuggestedCategories(keywords As String) As List(Of String)
    '<STAThread>
    Dim endpoint As String = "https://api.ebay.com/wsapi"
    Dim callName As String = "GetSuggestedCategories"
    Dim siteId As String = SiteCodeType.US
    Dim appId As String = "My App ID"
    Dim devId As String = "My Dev ID"
    Dim certId As String = "My Cert ID"
    Dim version As String = "1031"

    'build the request URL
    Dim requestURL As String = endpoint +
        "?callname=" + callName +
        "&siteid=" + siteId +
        "&appid=" + appId +
        "&version=" + version +
        "&routing=default"

    'Create the service
    Dim service As eBayAPIInterfaceClient = New eBayAPIInterfaceClient("eBayAPI", requestURL)
    Dim requesterCredentials As CustomSecurityHeaderType = New CustomSecurityHeaderType
    requesterCredentials.eBayAuthToken = "My User Token"
    requesterCredentials.Credentials = New UserIdPasswordType
    requesterCredentials.Credentials.AppId = appId
    requesterCredentials.Credentials.DevId = devId
    requesterCredentials.Credentials.AuthCert = certId

    'Make the call to GetSuggestedCategories
    Dim request As eBayWSDL.GetSuggestedCategoriesRequestType = New GetSuggestedCategoriesRequestType
    request.Version = version
    Dim ipHost As IPHostEntry = System.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName())        
    For Each ipaddress As IPAddress In ipHost.AddressList
        Debug.Print(ipaddress.ToString)
        If ipaddress.AddressFamily = Sockets.AddressFamily.InterNetwork Then
            request.EndUserIP = ipHost.AddressList(2).ToString
            Exit For
        End If
    Next
    request.Query = keywords
    Dim detaillevels As New List(Of DetailLevelCodeType)
    detaillevels.Add(DetailLevelCodeType.ReturnAll)
    request.DetailLevel = detaillevels.ToArray

    Dim returnCategories As New List(Of String)
    Dim response As GetSuggestedCategoriesResponseType
    Try
        response = service.GetSuggestedCategories(requesterCredentials, request)
        If response.Ack <> AckCodeType.Failure Then
            returnCategories.Add("0: Complete with no errors.")
            returnCategories.Add(response.SuggestedCategoryArray.SuggestedCategory.FirstOrDefault.Category.CategoryID)
        Else
            returnCategories.Add("1: Errors returned.")
            Dim err As ErrorType
            For Each err In response.Errors
                returnCategories.Add(response.Errors(0).ErrorCode + ": " + response.Errors(0).ShortMessage)
            Next err

        End If
    Catch ex As Exception
    Finally
        service.Close()
        service = Nothing
        requesterCredentials = Nothing
        request = Nothing
        response = Nothing
    End Try
    Return returnCategories

When I run this code the response returns with an ACK code of "Success" but the values are all empty. Below is an image that shows the object with empty values.

response Watch List

Based on the documentation from eBay, I am expecting the response.SuggestedCategoryArray.SuggestedCategory to be filled with 1 or more categories where I can pull the name, id, etc of the category.

I have attempted to run queries including "furniture", "red chair", "painting", "art", and "o'keefe" as some of these are specifically recommended by the documentation as examples to see differences in returns when broad or specific requests are made. Everything returns with an empty response.SuggestedCategoryArray.


Solution

  • After an additional day of research, trial, and uncountable errors I seem to have come across a way to deal with this issue.

    The key is that the response object has many properties but none of them get filled in any way. It may be because these were used in some earlier implementation of the objects but are no longer used. You can see that nothing is filled except the "Any" property, which is the key.

    The "Any" property receives an XmlElement object which contains the full response in XmlFormat. All I did was parse the Xml into an XDocument, then use LINQ to find and read the elements I was looking for, In the case of Getsuggestedcategories, I found the CategoryID elements and output the values to a list.

    Here is a snippit of my code changes starting with the instanciating of the response object.

    Dim response As GetSuggestedCategoriesResponseType = asyncResponse.GetSuggestedCategoriesResponse1
            If response.Ack <> AckCodeType.Failure Then
                If Not response.SuggestedCategoryArray Is Nothing Then
                    For Each cID In response.SuggestedCategoryArray.SuggestedCategory
                        returnCategories.Add(cID.Category.CategoryID)
                    Next
                ElseIf Not response.Any Is Nothing Then
                    returnCategories.Add("0: Complete with no errors.")
                    For Each xmlResponse In response.Any
                        Dim xmlConverter As New XmlDocumentConverter(xmlResponse)
                        returnCategories.AddRange(xmlConverter.ConvertToStringList("CategoryID"))
                    Next
                Else
                    returnCategories.Add("2: No Suggested Categories Were Found.")
                End If
            Else
                returnCategories.Add("1: Errors returned.")
                Dim err As ErrorType
                For Each err In response.Errors
                    returnCategories.Add(response.Errors(0).ErrorCode + ": " + response.Errors(0).ShortMessage)
                Next err
    
            End If
        Catch ex As Exception
        Finally
            service.Close()
            service = Nothing
            requesterCredentials = Nothing
            request = Nothing
            asyncResponse = Nothing
        End Try
        Return returnCategories
    

    And here is the code I created for the XmlConverter, which reads the xmlElement and return a list of string values.

    Imports System.Globalization
    Imports System.IO
    Imports System.Xml
    
    Namespace Converters.XML
    Public Class XmlDocumentConverter
    
        Private xmlDoc As XDocument
    
        Public Sub New(xmlDocumentToRead As XmlDocument)
            xmlDoc = XDocument.Parse(xmlDocumentToRead.OuterXml)
        End Sub
    
        Public Sub New(xmlElementToRead As XmlElement)
            xmlDoc = XDocument.Parse(xmlElementToRead.OuterXml)
        End Sub
    
        ''' <summary>
        ''' This will take the nodeToFind representing the xDocument.Name.LocalName and will return the contained value within all found elements.
        ''' </summary>
        ''' <param name="nodeToFind">The string matching the xDocument.Name.LocalName that you would like to find.</param>
        ''' <param name="returnAllResults">If True, returns all results. If False, returns the first result</param>
        ''' <returns></returns>
        Public Function ConvertToStringList(nodeToFind As String, Optional returnAllResults As Boolean = True) As List(Of String)
            Dim returnStringList = New List(Of String)
    
            Dim xElementList As New List(Of XElement)
            xElementList.AddRange(xmlDoc.Root.Descendants.Where(Function(x) x.Name.LocalName = nodeToFind))
            For Each e In xElementList
                returnStringList.Add(e.Value)
                If returnAllResults = False Then Exit For
            Next
    
            Return returnStringList
        End Function
    
    End Class
    

    End Namespace

    Feedback and suggestions are still welcome as this is the best answer I could come up with, but welcome anyone with better ideas or implementations of the eBay API.