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