Amazon.com Web Service Details
Amazon.com offers several Web Services that allow developers the opportunity to integrate Amazon.com features and content directly into their Web sites. While it isn't difficult to include a Web Reference within your Visual Studio project, I'll describe the some of the details here with the specific information to access one of these services. I'll also illustrate a technique that allows you to create a DataSet from objects returned from Web Services and bind their data to a DataGrid.
Philip Quinn (wisemonk) has already posted a fine article here on AspAlliance: Integrating Amazon Web Services on your Site. Please refer to this article for additional information on the Amazon.com services. I'll be dealing with the specifics of a single Web Service feature that returns information in the form of an array of Amazon.com's Details objects.
The information returned from the Web Service is for a list of books identified by their "ASIN". Every unique product in Amazon.com's catalog has an "ASIN", which is short for "Amazon Standard Item Number". For the books category, the ASIN is the same as its "International Standard Book Number", or "ISBN".
In order to use Amazon.com Web Services, you first need to register and obtain a valid developer token - Apply Now (it's easy and free). You should also download the Developer's Kit that provides some useful information. In the following examples I'll be using an invalid developer token (DT123456789AMZ).
In the following example we'll create a two simple pages that present each book's detailed information in a DataGrid bound to a DataSet that we create from the Details objects returned by the Web Service. The first page we create is just for initial testing and allows us to explore all of the information returned from the Web Service. The second page presents a more polished display version of the same information in using DataGrid TemplateColumns to format the information.
Step 1 - Create the Web Reference
In this first step we use Visual Studio's Solution Explorer and right click on the Web References item and choose Add Web Reference. In the Web Reference window's address field, enter http://soap.amazon.com/schemas/AmazonWebServices.wsdl and click the "Add Reference" button. This will automatically generate the Web Reference with a proxy class named "com.amazon.soap" within your project's namespace. To keep the references short in this example, I'll rename this Web Reference in the Solution Explorer from "com.amazon.soap" to simply "Amazon".
Step 2 - Create the Books Display Page (info version)
We start with a very simple Web Form that we'll use to display the raw information returned from the Amazon.com Web Service call. The form initially contains three DataGrids and a Label that helps us understand the underlying Amazon.Details data structure. At this stage our Books.aspx page includes:
<form id="Books" method="post" runat="server">
<asp:DataGrid id="DataGrid1" runat="server"></asp:DataGrid>
<asp:DataGrid id="DataGrid2" runat="server"></asp:DataGrid>
<asp:DataGrid id="DataGrid2" runat="server"></asp:DataGrid><br>
<asp:Label id="Label1" runat="server">Label</asp:Label>
</form>
We'll look at the complete Books.aspx.cs codebehind file in more detail later; but for now let's concentrate on the beginning of the LoadBooks method that actually invokes the Amazon.com Web Service. As illustrated below, LoadBooks is called from Page_Load and passed a simple string with 4 comma delimited ASINs of the books we want to display.
private void Page_Load(object sender, System.EventArgs e)
{
Label1.Visible = false;
if ( ! IsPostBack )
{
LoadBooks("0735614229,1590590392,0735615829,1590590104");
}
}
private void LoadBooks(string asinList )
{
// create the Web Service (proxy) object
Amazon.AmazonSearchService ws = new
Amazon.AmazonSearchService();
// create the request object
Amazon.AsinRequest request = new Amazon.AsinRequest();
request.asin = asinList;
request.type = "lite";
request.devtag = "DT123456789AMZ";
Amazon.ProductInfo info;
try
{
info = ws.AsinSearchRequest( request );
}
catch( Exception ex )
{
ShowError(ex.Message);
return;
}
.
.
.
The first thing we do in the LoadBooks method is create an object of our generated proxy class that we use to invoke the AsinSearchRequest method. This method takes a single Amazon.AsinRequest object as an argument. You can find the member details of the AsinRequest class by looking in the Amazon Toolkit documentation, or you can refer to the generated proxy class.
Through testing I've found that the three members of the AsinRequest object that need to be supplied for this method call include: the comma delimited list of ASINs (asin), the request type (heavy or lite), and your Amazon Developer Token (devtag). You'll find in the documentation that a request type of "heavy" returns more information about each item, but limits the number of ASINs to 10 for each Web Service call. The "lite" request type returns somewhat less information, but allows you to specify up to 30 ASINs at a time.
The AsinSearchRequest method returns an Amazon.ProductInfo object. The method call appears within a try/catch block to report back any errors encountered in the Web Service call.
You can examine the members of the Amazon.ProductInfo class in the Toolkit documentation or by referring to the proxy class definition. We're going to concentrate on a single member of this class named "Details" that is an array of Amazon.Details objects. Each item in the array contains the detail information for one of the books in our list of ASINs.
Step 3 - Load DataSet with Book Details
This next snippet of code (the remainder of the LoadBooks method) is one of my favorites that we use here to examine object arrays. During this initial test, we want to load the info.Details array into a DataSet and then bind it to our DataGrids. We accomplish this by serializing the info.Details array into XML, and then reading the XML into a DataSet.
.
.
.
// convert the info.Details array to XML and load DataSet
XmlSerializer xmlSerializer =
new XmlSerializer( info.Details.GetType() );
StringWriter writer = new StringWriter();
xmlSerializer.Serialize(writer, info.Details );
StringReader reader = new StringReader( writer.ToString() );
dataset = new DataSet();
dataset.ReadXml( reader );
// bind the two grids
DataGrid1.DataSource = dataset.Tables[0];
DataGrid1.DataBind();
DataGrid2.DataSource = dataset.Tables[1];
DataGrid2.DataBind();
if ( dataset.Tables.Count > 2 )
{
DataGrid3.DataSource = dataset.Tables[2];
DataGrid3.DataBind();
}
}
We use a StringWriter and StringReader along with the XmlSerializer to get both a default schema and the Details array contents into our DataSet. As you'll see when you run this demo, we actually get three tables in our DataSet: one that contains the information for each book, and, since each book may have more than one author, two additional tables identifying the authors.
Article Update 11/20/2003 -- The Amazon Web Service has changed since the writing of this article and the following links to the demo may not work properly.
Run information demo now...
At this stage of the example we have a pretty rough grid display of the book details and two separate grids with the authors. The DataSet's ReadXml method, along with the XmlSerializer output, creates the two author tables automatically because each of the Amazon.Details objects in the array contain yet another array of the book's authors. A word of caution: if all of the books in the list reference only one author each, then the second grid's reference table will not be created. This is why we check the dataset.Tables.Count before binding all three grids. Try this yourself to see the results with a different list of ASINs.
Step 4 - Bind a Display Version of DataGrid
In this final step we replace our three informational DataGrids with a single DataGrid that represents our final display version of the book details. We set the grid's AutoGenerateColumns to false and bind specific columns from our DataSet's tables to the DataGrid. We show the book cover image, a few of the more interesting details about each book, and a coalesced list of the book's authors.
Run final demo now...
The DataGrid definition in the Books2.aspx page includes:
asp:DataGrid id="bookGrid" runat="server"
BorderColor="#DEDFDE" BorderStyle="None"
BorderWidth="1px" BackColor="White" CellPadding="4" GridLines="Vertical"
ForeColor="Black" ShowHeader="False" AutoGenerateColumns="False">
<SelectedItemStyle Font-Bold="True" ForeColor="White"
BackColor="#CE5D5A"></SelectedItemStyle>
<AlternatingItemStyle BackColor="White"></AlternatingItemStyle>
<ItemStyle BackColor="#F7F7DE"></ItemStyle>
<Columns>
<asp:TemplateColumn>
<ItemTemplate>
<a href='<%# DataBinder.Eval( Container.DataItem, "Url" ) %>' >
<IMG src='<%# DataBinder.Eval( Container.DataItem, "ImageUrlMedium" ) %>'
border="0" alt="cover" hspace="3" vspace="3" height="100"></a>
</ItemTemplate>
</asp:TemplateColumn>
<asp:TemplateColumn ItemStyle-VerticalAlign="Top">
<ItemTemplate>
<b><%# DataBinder.Eval(
Container.DataItem, "ProductName" ) %></b><br>
By <%# GetAuthors(
DataBinder.Eval( Container.DataItem, "Details_Id" ).ToString() ) %>
<br>From <%# DataBinder.Eval( Container.DataItem, "Manufacturer" ) %><br>
Amazon Price <%# DataBinder.Eval( Container.DataItem, "OurPrice" ) %>
</ItemTemplate>
</asp:TemplateColumn>
</Columns>
</asp:DataGrid>
We're not going to address the details ItemTemplates or data binding, except to show the method by which we coalesce the list of authors for each book. If you examine the second ItemTemplate above, you'll see the item that displays the list of authors actually invokes the GetAuthors method in our Books2.aspx.cs codebehind file.
public string GetAuthors( string id )
{
DataRow[] rows;
if ( dataset.Tables.Count > 2 )
rows = dataset.Tables[2].Select( "Authors_Id=" + id );
else
rows = dataset.Tables[1].Select( "Details_Id=" + id );
string names = "";
for( int i = 0; i < rows.Length; i++ )
{
if ( i > 0 )
names += (i == rows.Length - 1 ) ? " and " : ", ";
names += rows[i][0].ToString();
}
return names;
}
The GetAuthors method uses the Details_Id column from the main (1st) table as the key to select all of the matching rows in the authors' table. Remember the caveat: there may be either one or two tables for the authors depending on the actual ASINs selected. In this example we're actually ignoring the "reference" table if it exists--but it still works because of this simplistic relationship and our knowledge of the data relation.
Summary
It's clear that Amazon.com is committed to providing an ever expanding set of features that developers will be able to access. Extend this example to show different information for each book and look in to at all of the different Web Service features that Amazon.com is providing. While these examples may seem a bit lengthy, it's really quite simple to create Web Service references with Visual Studio, WebMatrix or even the command line tools.
Get the source files used in these examples with this link for the Books.zip file--and be sure to use your own Amazon.com Developer's Token.
Books.zip
Send your comments and let me know what you think of this article: steve@sharkcode.com
Steve Sharrock - www.AspAlliance.com/shark / www.SharkCode.com