Working with Amazon Search Web Service using ASP.NET
page 3 of 4
by Anand Vijayan
Feedback
Average Rating: 
Views (Total / Last 10 Days): 24371/ 32

Object Oriented Design Approach

Abstraction

Dto.BaseDto: This class abstracts the common properties and methods for serialization and de-serialization.

Request Classes

Dto.Request: The data being requested is stored in the Request class. It also encapsulates the logic to build the ItemLookupRequest. The ResponseGroup property specifies a list of properties that need to be present in the response like editorial review, price, etc. The advantage of this is that only specific parameters can be queried, thus avoiding information overload. Note that the ItemLookupRequestIdType.ASIN is used here. Amazon.com used an ASIN to identify any item that is listed on their site.

Listing 1 – Building the ItemLookupRequest

[XmlInclude(typeof(Request)), XmlInclude(typeof(ISBNRequest))]
public class Request: Base
{
  [XmlElement("Keywords", typeof(string))]
  public string m_keywords = string.Empty;
  [XmlElement("SearchKey", typeof(string))]
  public string m_searchKey = string.Empty;
  protected webservices.amazon.com.ItemLookupRequest m_itemLookupRequest = new
    webservices.amazon.com.ItemLookupRequest();
 
  public Request()
  {
  }
  public Request(string keywords)
  {
    this.m_keywords = keywords;
  }
 
  public Request(string keywords, string key)
  {
    this.m_keywords = keywords;
    this.m_searchKey = key;
  }
 
  [XmlIgnore]
  public virtual webservices.amazon.com.ItemLookupRequest AWSItemLookupRequest
  {
    get
    {
      m_itemLookupRequest.Condition = webservices.amazon.com.Condition.All;
      m_itemLookupRequest.MerchantId = "All";
      string[]responseGroup =
      {
        "ItemAttributes", "Offers""EditorialReview"
      };
      m_itemLookupRequest.ResponseGroup = responseGroup;
      this.m_itemLookupRequest.IdType =
        webservices.amazon.com.ItemLookupRequestIdType.ASIN;
      this.m_itemLookupRequest.IdTypeSpecified = true;
      string[]keywords =
      {
        this.m_keywords
      };
      this.m_itemLookupRequest.ItemId = keywords;
      return this.m_itemLookupRequest;
    }
  }
 
}

Dto.ISBNRequest: If the data being requested is an ISBN for a book, it is stored in the ISBNRequest class. It is quite similar to the Request except for the validation of ISBN and the ItemLookupRequestIdType.ISBN. This indicates that the item being requested is a book whose ISBN has been supplied as a keyword.

Listing 2 – Building the ItemLookupRequest

[XmlInclude(typeof(ISBNRequest))]
public class ISBNRequest: Request
{
  public ISBNRequest()
  {
    this.m_searchKey = System.Configuration.ConfigurationManager.AppSettings[
      "AmazonWS.BookSearch.Key"];
  }
 
  public ISBNRequest(string isbn)
  {
    this.m_keywords = isbn;
    this.m_searchKey = System.Configuration.ConfigurationManager.AppSettings[
      "AmazonWS.BookSearch.Key"];
    this.m_isvalid = ValidateISBN();
  }
  [XmlIgnore]
  public override webservices.amazon.com.ItemLookupRequest AWSItemLookupRequest
  {
    get
    {
      this.m_itemLookupRequest = base.AWSItemLookupRequest;
      this.m_itemLookupRequest.SearchIndex = this.m_searchKey;
      this.m_itemLookupRequest.IdType =
        webservices.amazon.com.ItemLookupRequestIdType.ISBN;
      this.m_itemLookupRequest.IdTypeSpecified = true;
      return this.m_itemLookupRequest;
    }
  }
  …
}

Dto. RequestList: Multiple requests are sent in List<Request> class. Its constructor takes in a serialized xml version of the RequestList and encapsulates the logic to build the ItemLookupRequest[]. If the request is of type ISBNRequest, the ISBN validation is done after deserialization. This needs to be done as the ISBN validation in the ISBNRequest constructor does not get called during deserialization.

Listing 3

[XmlRoot("RequestList", Namespace = "")][XmlInclude(typeof(List < Request > ))]
public class RequestList: List < Request >
{
  …
  public RequestList(string xml)
  {
    List < Request > listReq = (List < Request > )Base.Deserialize(xml,
      this.GetType());
    foreach (Request request in listReq)
    {
      if (request is ISBNRequest)
        if (((ISBNRequest)request).ValidateISBN())
          request.m_isvalid = true;
        else
          throw new ApplicationException("Invalid ISBN '" + request.m_keywords
            + "' supplied");
      this.Add(request);
    }
  }
}

Response Classes

Dto.AWSResponse: This class builds the List<Response> and the List<ReturnMg>. The SetAWSREsponse method checks for errors in the ItemLookupResponse and adds them to the List<ReturnMg>. If no errors are found, the List<Response> is constructed and a success message is added to the List<ReturnMg>.

Listing 4 – Building the AWSResponse

public class AWSResponse
{
  [XmlElement("Response")]
  public ResponseList m_responseList = new ResponseList();
  [XmlElement("RetMsg")]
  public ReturnMsgList m_returnMsg = new ReturnMsgList();
 
  … public void SetAWSResponse(webservices.amazon.com.ItemLookupResponse
    itemLookupResponse)
  {
    if (itemLookupResponse.OperationRequest.Errors == null ||
      itemLookupResponse.OperationRequest.Errors.Length == 0)
    {
      bool errorsFound = false;
      for (int i = 0; i < itemLookupResponse.Items.Length; i++)
      {
        if (itemLookupResponse.Items[i].Item != null)
        {
          this.m_responseList = new ResponseList
            (itemLookupResponse.Items[i].Item);
        }
        else
        {
          // Request Level Errors
          foreach (webservices.amazon.com.ErrorsError error in
            itemLookupResponse.Items[i].Request.Errors)
          {
            errorsFound = true;
            System.Diagnostics.Trace.WriteLine("Errors found in response. ");
            this.m_returnMsg.Add(new ReturnMsg("Error", error.Code + " - " +
              error.Message));
          }
        }
      }
 
      if (!errorsFound)
      {
        System.Diagnostics.Trace.WriteLine("Search was successful. ");
        this.m_returnMsg.Add(new ReturnMsg("Success""Search was successful"));
      }
    }
    else
    {
      // Operation Level Errors
      foreach (webservices.amazon.com.ErrorsError error in
        itemLookupResponse.OperationRequest.Errors)
      {
        System.Diagnostics.Trace.WriteLine("Errors found in response. ");
        this.m_returnMsg.Add(new ReturnMsg("Error", error.Code + " - " +
          error.Message));
      }
    }
  }
}
 
…
}

Dto.ResponseList: Responses for multiple requests are returned in the List<Response> class. It encapsulates the logic to parse the Item in the ItemLookupResponse and populate the required values such as ItemAttributes, Offers and EditorialReview into the Response.

Listing 5 – Retrieve the Items from the ItemLookupResponse

public class ResponseList: List < Response >
{
  …
 
  public ResponseList(webservices.amazon.com.Item[]items)
  {
    for (int j = 0; j < items.Length; j++)
    {
      Response response = new Response();
      response.m_awsItemAttributes = items[j].ItemAttributes;
      response.m_awsOffers = items[j].Offers;
      response.m_awsEditorialReviews = items[j].EditorialReviews;
      response.SetAWSResponse();
      this.Add(response);
    }
 
  }
}

Dto.Response: The Response class extracts the values from the ItemLookupResponse and populates itself. As the code below shows, the author, publisher and title are contained in the ItemAttributes. The price is contained in the Offers. The editorial reviews are contained in the EditorialReview.

Listing 6 – Parsing the ItemAttributes: Attributes, Price, Reviews

public class Response: Base
{
  …[XmlIgnore]
  public webservices.amazon.com.ItemAttributes m_awsItemAttributes = null;
  [XmlIgnore]
  public webservices.amazon.com.Offers m_awsOffers = null;
  [XmlIgnore]
  public webservices.amazon.com.EditorialReview[]m_awsEditorialReviews = null;
  …
  public void SetAWSResponse()
  {
    if (this.m_awsItemAttributes != null)
    {
      this.m_title = (this.m_awsItemAttributes.Title != null) ?
        this.m_awsItemAttributes.Title : string.Empty;
      if (this.m_awsItemAttributes.Author != null)
      {
        for (int aCount = 0; aCount < this.m_awsItemAttributes.Author.Length;
          aCount++)
          this.m_author += this.m_awsItemAttributes.Author[aCount] + ", ";
        this.m_author = this.m_author.Substring(0, this.m_author.Length - 2);
      }
 
      this.m_publisher = (this.m_awsItemAttributes.Manufacturer != null) ?
        this.m_awsItemAttributes.Manufacturer : string.Empty;
 
      if (this.m_awsOffers != null && this.m_awsOffers.Offer != null &&
        this.m_awsOffers.Offer[0].OfferListing != null &&
        this.m_awsOffers.Offer[0].OfferListing[0].Price != null)
      {
        this.m_price = (this.m_awsOffers.Offer[0].OfferListing[0].Price != null)
          ? this.m_awsOffers.Offer[0].OfferListing[0].Price.FormattedPrice:
          string.Empty;
      }
 
      if (this.m_awsEditorialReviews != null)
      {
        this.m_editorialReview = this.m_awsEditorialReviews[0].Content;
      }
    }
    …
  }

Dto.ReturnMg: This class encapsulates the return messages from AWS. In case of errors it will contain the error message. In case of a successful call to AWS it contains a success message.

Dto.List<ReturnMsg>: This is a list of return messages.

Utility Class

Util.AWSSearch: This class has a Search method that does the following tasks.

1.    Makes a call to the AWSECommerceService which is the AWS web service instance

2.    Instantiates the ItemLookup

3.    Populates the ItemLookupRequest[] from the List<Request> and assigns it to the ItemLookup.Request property

4.    Invokes the AWSECommerceService.ItemLookup webmethod and gets back the ItemLookupResponse

5.    It parses the ItemLookupResponse using the core ASWS classes, populates the AWSResponse and returns it.

Listing 7

public class AWSSearch
{
  …
  public AWSResponse Search()
  {
    AWSResponse awsResponse = new AWSResponse();
 
    try
    {
      if (m_requestList != null && m_requestList.Count > 0)
      {
        webservices.amazon.com.AWSECommerceService acs = new
          webservices.amazon.com.AWSECommerceService();
        webservices.amazon.com.ItemLookup itemLookup = new
          webservices.amazon.com.ItemLookup();
        itemLookup.AWSAccessKeyId = m_accessKeyID;
        webservices.amazon.com.ItemLookupRequest[]itemLookupRequests = new
          webservices.amazon.com.ItemLookupRequest[m_requestList.Count];
        for (int i = 0; i < this.m_requestList.Count; i++)
        {
          if (m_requestList[i]is ISBNRequest)
          {
            ISBNRequest isbnRequest = (ISBNRequest)m_requestList[i];
            itemLookupRequests[i] = isbnRequest.AWSItemLookupRequest;
          }
          else
          {
            itemLookupRequests[i] = m_requestList[i].AWSItemLookupRequest;
          }
        }
        itemLookup.Request = itemLookupRequests;
        webservices.amazon.com.ItemLookupResponse itemLookupResponse =
          acs.ItemLookup(itemLookup);
        awsResponse.SetAWSResponse(itemLookupResponse);
 
      }
      else
      {
        // Request Empty Error
        awsResponse.m_returnMsg.Add(new ReturnMsg("Error",
          "No requests where processed."));
      }
 
    }
    catch (Exception e)
    {
      System.Diagnostics.Trace.WriteLine(
        "An error occured when trying to Search. " + e.Message + " " +
        e.StackTrace);
      awsResponse.m_returnMsg.Add(new ReturnMsg("Error", e.Message));
    }
 
    return awsResponse;
  }
}

AmazonWebSearch Web Service: The web service has two main web methods.

Search(List<Request>): This web method accepts a List< Request> class and returns a AWSResponse. Any ASP.NET based thin client can call this web method, pass the List<Request> as input and get the AWSResponse as output.

SearchXml(string): This web method accepts an xml string input which is the serialized version of the List< Request> class. The xml is deserialized and passed to Search(List<Request> web method. The AWSResponse that is returned is serialized and returned. Any thin client irrespective of the platform can use this web method. This web method was tested with a PDA that had a J2ME (Java 2 Micro Edition) based application running.


View Entire Article

User Comments

Title: Base class   
Name: Sumit Rawat
Date: 2011-04-16 7:03:15 AM
Comment:
where is the code for the "Base" class. The "Base" class is made parent for Request and Response classes, so it should be included in the web page. Please give me the code for the base class.
Title: Working with Amazon Search Web Service using ASP.NET   
Name: Vijil jones
Date: 2008-06-11 12:56:58 AM
Comment:
How we get the Utility Class and other class

Product Spotlight
Product Spotlight 





Community Advice: ASP | SQL | XML | Regular Expressions | Windows


©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-03-28 10:10:59 PM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search