Retrieving a list of eBay categories using the .NET SDK and GetCategoriesCall

Posted by Bill Osuch on Geeks with Blogs See other posts from Geeks with Blogs or by Bill Osuch
Published on Mon, 25 Jun 2012 19:06:27 GMT Indexed on 2012/06/25 21:16 UTC
Read the original article Hit count: 327

Filed under:

eBay offers a .Net SDK for its Trading API - this post will show you the basics of making an API call and retrieving a list of current categories. You'll need the category ID(s) for any apps that post or search eBay.

To start, download the latest SDK from https://www.x.com/developers/ebay/documentation-tools/sdks/dotnet and create a new console app project.

Add a reference to the eBay.Service DLL, and a few using statements:

using eBay.Service.Call;
using eBay.Service.Core.Sdk;
using eBay.Service.Core.Soap;

I'm assuming at this point you've already joined the eBay Developer Network and gotten your app IDs and user tokens. If not:

Join the developer program
Generate tokens

Next, add an app.config file that looks like this:

<?xml version="1.0"?>
<configuration>
  <appSettings>
    <add key="Environment.ApiServerUrl" value="https://api.ebay.com/wsapi"/>
    <add key="UserAccount.ApiToken" value="YourBigLongToken"/>
  </appSettings>
</configuration>

And then add the code to get the xml list of categories:

ApiContext apiContext = GetApiContext();

GetCategoriesCall apiCall = new GetCategoriesCall(apiContext);
apiCall.CategorySiteID = "0";

//Leave this commented out to retrieve all category levels (all the way down):
//apiCall.LevelLimit = 4;

//Uncomment this to begin at a specific parent category:
//StringCollection parentCategories = new StringCollection();
//parentCategories.Add("63");
//apiCall.CategoryParent = parentCategories;

apiCall.DetailLevelList.Add(DetailLevelCodeType.ReturnAll);
CategoryTypeCollection cats = apiCall.GetCategories();

using (StreamWriter outfile = new StreamWriter(@"C:\Temp\EbayCategories.xml"))
{
   outfile.Write(apiCall.SoapResponse);
}

GetApiContext() (provided in the sample apps in the SDK) is required for any call:

        static ApiContext GetApiContext()
        {
            //apiContext is a singleton,
            //to avoid duplicate configuration reading
            if (apiContext != null)
            {
                return apiContext;
            }
            else
            {
                apiContext = new ApiContext();

                //set Api Server Url
                apiContext.SoapApiServerUrl = ConfigurationManager.AppSettings["Environment.ApiServerUrl"];
                //set Api Token to access eBay Api Server
                ApiCredential apiCredential = new ApiCredential();
                apiCredential.eBayToken = ConfigurationManager.AppSettings["UserAccount.ApiToken"];
                apiContext.ApiCredential = apiCredential;
                //set eBay Site target to US
                apiContext.Site = SiteCodeType.US;

                return apiContext;
            }
        }

Running this will give you a large (4 or 5 megs) XML file that looks something like this:

<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Body>
      <GetCategoriesResponse >
         <Timestamp>2012-06-06T16:03:46.158Z</Timestamp>
         <Ack>Success</Ack>
         <CorrelationID>d02dd9e3-295a-4268-9ea5-554eeb2e0e18</CorrelationID>
         <Version>775</Version>
         <Build>E775_CORE_BUNDLED_14891042_R1</Build> -
         <CategoryArray>
            <Category>
               <BestOfferEnabled>true</BestOfferEnabled>
               <AutoPayEnabled>true</AutoPayEnabled>
               <CategoryID>20081</CategoryID>
               <CategoryLevel>1</CategoryLevel>
               <CategoryName>Antiques</CategoryName>
               <CategoryParentID>20081</CategoryParentID>
            </Category>
            <Category>
               <BestOfferEnabled>true</BestOfferEnabled>
               <AutoPayEnabled>true</AutoPayEnabled>
               <CategoryID>37903</CategoryID>
               <CategoryLevel>2</CategoryLevel>
               <CategoryName>Antiquities</CategoryName>
               <CategoryParentID>20081</CategoryParentID>
            </Category>
(etc.)

You could work with this, but I wanted a nicely nested view, like this:

<CategoryArray>
   <Category Name='Antiques' ID='20081' Level='1'>
      <Category Name='Antiquities' ID='37903' Level='2'/>
</CategoryArray>

...so I transformed the xml:

private void TransformXML(CategoryTypeCollection cats)
        {
            XmlElement topLevelElement = null;
            XmlElement childLevelElement = null;
            XmlNode parentNode = null;
            string categoryString = "";

            XmlDocument returnDoc = new XmlDocument();
            XmlElement root = returnDoc.CreateElement("CategoryArray");
            returnDoc.AppendChild(root);

            XmlNode rootNode = returnDoc.SelectSingleNode("/CategoryArray");

            //Loop through CategoryTypeCollection
            foreach (CategoryType category in cats)
            {
                if (category.CategoryLevel == 1)
                {
                    //Top-level category, so we know we can just add it
                    topLevelElement = returnDoc.CreateElement("Category");
                    topLevelElement.SetAttribute("Name", category.CategoryName);
                    topLevelElement.SetAttribute("ID", category.CategoryID);
                    rootNode.AppendChild(topLevelElement);
                }
                else
                {
                    // Level number will determine how many Category nodes we are deep
                    categoryString = "";
                    for (int x = 1; x < category.CategoryLevel; x++)
                    {
                        categoryString += "/Category";
                    }
                    parentNode = returnDoc.SelectSingleNode("/CategoryArray" + categoryString + "[@ID='" + category.CategoryParentID[0] + "']");
                    childLevelElement = returnDoc.CreateElement("Category");
                    childLevelElement.SetAttribute("Name", category.CategoryName);
                    childLevelElement.SetAttribute("ID", category.CategoryID);
                    parentNode.AppendChild(childLevelElement);
                }
            }

            returnDoc.Save(@"C:\Temp\EbayCategories-Modified.xml");
        }

Yes, there are probably much cleaner ways of dealing with it, but I'm not an xml expert…

Keep in mind, eBay categories do not change on a regular basis, so you should be able to cache this data (either in a file or database) for some time. The xml returns a CategoryVersion node that you can use to determine if the category list has changed.

Technorati Tags: ,

© Geeks with Blogs or respective owner