Use Amazon Web Services in ASP.NET

If you’ve used the Internet to shop, you’ve no doubt used Amazon at some point. As one of the few etailers to survive the dot com crash in the late 90s, Amazon is going from strength to strength. Using the powerful Amazon Web Service program, you can offer your visitors new features and suggestions, and make some money in the process.

Amazon Web Services 4.0

Exactly what is a Web service? A Web service allows you to extract and distribute the specific aspects of the functionality of applications so that those aspects can be reused by other applications. Web services enable Amazon to provide developers with detailed interfaces to its catalogue systems. This lets you as the developer send queries to Amazon, and retrieve structured results to use within your application, as we’ll see in this article.

Dos and Don’ts

Now at version 4.0, the Amazon services require a subscription ID that you must pass with all requests to the service. In this way, your usage is monitored and restrictions can be applied to those who mis-use the service.

Subscription is the first, essential step that will enable you to use Amazon services, so be sure to register and receive your subscription ID.

So, what are these restrictions I mentioned? Firstly, you cannot make more than 1 request per second. This isn’t a hard restriction that’s enforced automatically; however, you will break the license agreement if you exceed this limit.

Restrictions are also placed on caching. To keep your application response times smooth and fast, it’s essential that you cache results from Web services. With Amazon Web services, you cannot keep product information within your system cache for longer than 24 hours (note that there are certain products whose information can remain in cache longer than this; check the license agreement for details). This helps ensure the information you present to your visitors is synchronized with the Amazon catalogue. In addition, any cached results that are more than an hour old must have a time stamp attached to show exactly when the information was retrieved from Amazon.

Finally, this disclaimer must be attached to all pricing information:

"Price is accurate as of the date/time indicated. Prices and product availability are subject to change. Any price displayed on the Amazon website at the time of purchase will govern the sale of this product."

Using the Amazon Web Services 4.0: Getting Started

Note: I’ve used Visual Web Developer 2005 Express Beta (which you can download for free) to develop the following Web applications; however, the process is identical for those using Visual Studio .NET 2003.

Once you’ve obtained your subscription ID, you can start to develop a simple application to retrieve the price of a book.

  1. Open up Visual Studio, and create a new Web application:
  2. 1419_image1

  3. Create a Web Reference to Amazon Web Services.
  4. Now that the Web service reference is in your application, you can build a simple GUI to retrieve and display the book search query.
    • Drop a textbox, a button, and a label onto the Web form in your new application.

1419_image3

You can now start to use the service. There are several ways to search and retrieve information from Amazon, but the one we’ll use will be ItemSearch. ItemSearch allows you to build a search using criteria such as keywords, titles, or manufacturer. However, ItemLookup allows you to make specific searches, for example, using an ISBN number for a product.

Double click on the button you’ve just dropped. This opens the button click event handler code. Now, enter the following code:

//namespace 
using com_webservices_amazon

AWSECommerceService aws = new AWSECommerceService();
ItemSearchRequest request = new ItemSearchRequest();

request.SearchIndex = "Books";
request.Power = "title:" + TextBox1.Text;
request.ResponseGroup = new string[] { "Small" };
request.Sort = "salesrank";

ItemSearchRequest[] requests = new ItemSearchRequest[] { request };

ItemSearch itemSearch = new ItemSearch();
itemSearch.AssociateTag = "myassociatetag-20";
itemSearch.SubscriptionId = "XXXXXXXXXXXXXXXXX";
itemSearch.Request = requests;

try
{
 ItemSearchResponse response = aws.ItemSearch(itemSearch);
 Items info = response.Items[0];
 Item[] items = info.Item;
 Label1.Text = "";
 for (int i = 0; i < items.Length; i++)
 {
   Item item = items[i];
   Label1.Text += "Book Title: " + item.ItemAttributes.Title + "<br />";
 }
}
catch (Exception ex)
{
 Label1.Text = (ex.ToString());
}

Looks complicated? Let’s break it down. The first step with any Amazon query is to create an instance of the service, and of the search type we wish to perform:

AWSECommerceService aws = new AWSECommerceService();
ItemSearchRequest request = new ItemSearchRequest();

We can then fill our request object with the details of the types of products we want to return.

request.SearchIndex = "Books"; 
request.Power = "title:" + TextBox1.Text;
request.ResponseGroup = new string[] { "Small" };
request.Sort = "salesrank";
SearchIndex specifies the particular catalogue we're going to search. Amazon has made available a full list of the catalogues you can search. Power uses the Amazon Power Search syntax to enable in-depth field searching, which is particularly useful with books.

In the example above, we're searching for titles that contain the string entered in the text box on our form. We could change this to "author:" to search for authors, or combine these to produce complex queries. A full reference of the Amazon Power Search is also available.

Alternatively, we can use the following to return all books through a simple keyword search:

request.Keywords = TextBox1.Text;

The response group attribute allows us to tailor the results from our search to contain only the information we need. "Small" has been used as this includes all the data necessary to display a typical item in a search results listing (product name, author, URL to Amazon etc.). Check out the full list of the types of response groups you can use to better tailor your search.

Finally, we specify that we wish to sort our results by their sale rankings on Amazon. Hence, more popular products will appear higher in our results. You can sort search results on any of the sorting types in this list.

ItemSearchRequest[] requests = new ItemSearchRequest[] { request };

We can now add our request object to an array of search requests. This structure is used so that, in future, we can submit more searches for fulfilment in one request.

ItemSearch itemSearch = new ItemSearch(); 
itemSearch.AssociateTag = "myassociatetag-20";
itemSearch.SubscriptionId = "XXXXXXXXXXXXXXXXX";
itemSearch.Request = requests;

The next stage in the process is to create an ItemSearch object that encapsulates our search requests and the details of our registration with Amazon (subscription ID and associate tag, if you have one). Using the associate tag, all URLs generated by the service will point towards your associate account, meaning you will be paid for any products that are bought on referral from your site.

We can now execute our search using the aws service instance we created earlier. We store the results of the query inside an ItemSearchResponse object; the actual product results are available through an Item object.

ItemSearchResponse response = aws.ItemSearch(itemSearch);

As I mentioned previously, we can send multiple search requests to the Amazon service at the same time; these are accessible through the response.Items collection. In this case, we have only sent one query, hence our results are stored in the first item in this collection -- the result collection is located inside this:

Items info = response.Items[0];
 Item[] items = info.Item;

We're now at the level of our particular search items. Iterating through the items collection, we can retrieve the specific values of our results via the ItemAttributes property of an item. The example below displays the title of a book:

Label1.Text = "";
 for (int i = 0; i < items.Length; i++)
 {
   Item item = items[i];
   Label1.Text += "Book Title: " + item.ItemAttributes.Title + "<br />";
 }
}

If we run the application, and enter a query for ASP.NET, we get the following results:

1419_image4

Caching

As we discussed previously, Amazon services need to be cached. Thanks to .NET's simple-to-use caching engine, we can add caching abilities to our application in a few short lines.

First, we need to add the response of our search to the cache. This is held in the ItemSearchResponse response object. The key to accessing the result from the cache is given by the value stored within the text box -- the unique part of our search query. As per the license agreement requirements, this cache item will expire in 24 hours after we add it:

Cache.Insert(TextBox1.Text.ToLower(), response, null,  
   DateTime.Now.AddHours(24), TimeSpan.Zero);

At the start of our query, we can now check to see if we already have our item in the cache, using the TextBox1.Text as our key:

if (Cache[TextBox1.Text.ToLower()] == null)

If we haven't got a cached result for the query, we can use the code defined earlier to go grab it. Otherwise, we need to retrieve our ItemSearchResponse from the system cache:

response = (ItemSearchResponse)Cache[TextBox1.Text];

Our completed code looks like this, with caching enabled (new lines are bolded):

//have we this in the cache already?  
ItemSearchResponse response;  
if (Cache[TextBox1.Text] == null)  
{  
 AWSECommerceService aws = new AWSECommerceService();  
 ItemSearchRequest request = new ItemSearchRequest();  
 
 request.SearchIndex = "Books";  
 
 request.Power = "title:" + TextBox1.Text;  
 request.ResponseGroup = new string[] { "Small" };  
 request.Sort = "salesrank";  
 
 ItemSearchRequest[] requests = new ItemSearchRequest[] { request };  
 
 ItemSearch itemSearch = new ItemSearch();  
 itemSearch.AssociateTag = "myassociatetag-20";  
 itemSearch.SubscriptionId = "XXXXXXXXXXXXXXXXX";  
 itemSearch.Request = requests;  
 
 response = aws.ItemSearch(itemSearch);  
 Cache.Insert(TextBox1.Text, response, null,  
     DateTime.Now.AddHours(24), TimeSpan.Zero);  
}else  
{  
 response = (ItemSearchResponse)Cache[TextBox1.Text];  
}  
Items info = response.Items[0];  
Item[] items = info.Item;  
Label1.Text = "";  
for (int i = 0; i < items.Length; i++)  
{  
 Item item = items[i];  
 Label1.Text += "Book Title: " + item.ItemAttributes.Title + "<br />";  
}  
}
Amazon Web Service to DataSet

It's now time to encapsulate this functionality so that we can reuse the service more easily. The DataSet type within .NET is perfect for displaying structured data on our Web forms.

Our code will be sectioned into two methods. The AmazonToDataSet method will produce a DataSet from an ItemSearchResponse object; grabAmazonSearch will encapsulate our code to retrieve the ItemSearchResponse from a query string:

public DataSet AmazonToDataSet(string PowerSearchString)  
{  
 
 DataSet ds;  
 
 //have we this in the cache already?  
 if (Cache[PowerSearchString] == null)  
 {  
   //create our query  
   ItemSearchResponse response =  
       grabAmazonSearch(PowerSearchString);  
 
   //Construct the dataset to store the results  
   ds = new DataSet();  
   ds.Tables.Add();  
 
   ds.Tables[0].Columns.Add("ProductName");  
   ds.Tables[0].Columns.Add("AuthorName");  
   ds.Tables[0].Columns.Add("Price");  
   ds.Tables[0].Columns.Add("URL");  
 
   Items info = response.Items[0];  
   Item[] items = info.Item;  
   DataRow dr;  
 
   //iterate the results adding new rows with  
   //the values from the search result item.  
 
   for (int i = 0; i < items.Length; i++)  
   {  
     Item item = items[i];  
     dr = ds.Tables[0].NewRow();  
     dr["ProductName"] = item.ItemAttributes.Title;  
     dr["AuthorName"] = item.ItemAttributes.Author[0];  
     dr["Price"] = item.ItemAttributes.ListPrice;  
     dr["URL"] = item.DetailPageURL;  
     ds.Tables[0].Rows.Add(dr);  
   }  
   
   //add the dataset to the cache  
   Cache.Insert(PowerSearchString, ds, null,  
       DateTime.Now.AddHours(24), TimeSpan.Zero);  
 
 }  
 else  
 {  
   ds = (DataSet)Cache[PowerSearchString];  
 }  
//return the dataset  
return ds;  
}  
 
 
private ItemSearchResponse grabAmazonSearch(string PowerSearchString)  
{  
 ItemSearchResponse response;  
 AWSECommerceService aws = new AWSECommerceService();  
 ItemSearchRequest request = new ItemSearchRequest();  
 
 request.SearchIndex = "Books";  
 
 request.Power = PowerSearchString;  
 request.ResponseGroup = new string[] { "Small" };  
 request.Sort = "salesrank";  
 
 ItemSearchRequest[] requests = new ItemSearchRequest[] { request };  
 
 ItemSearch itemSearch = new ItemSearch();  
 itemSearch.AssociateTag = "myassociatetag-20";  
 itemSearch.SubscriptionId = "XXXXXXXXXXXXXXX";  
 itemSearch.Request = requests;  
           
 response = aws.ItemSearch(itemSearch);  
 
 return response;  
}

If we drop a DataGrid onto a Web form, we can fill it with the results from an Amazon query in just two lines of code:

Datagrid1.DataSource = AmazonToDataSet("title: " + TextBox1.Text);  
 Datagrid1.DataBind();

This provides the following output:

1419_image5

Summary

Using Amazon Web Services on your Website can create new revenue opportunities for your site, and provide fresh content for your users to view. Make the most of it!

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • Anyoneneo

    Thanks a lot for sharing this very useful code! one question, why is Price column is blank?

  • chandra malla

    I was trying to learn about amazon web services, it was nice tutorial , thanks….

  • Raj

    Everytime I do this, I get the following error

    Unable to generate a temporary class (result=1).
    error CS0029: Cannot implicitly convert type ‘uk.co.amazon.webservices.ImageSet’ to ‘uk.co.amazon.webservices.ImageSet[]‘

    I have tried to change the endpoint to UK too and I get the same issue. Any suggestions?

    (Alsom what is the associateTag?)

    Thanks