アーカイブ

Posts Tagged ‘Silverlight AWS’

Silverlightでamazonの書籍検索を使ってみよう

2010年12月24日 4件のコメント

書籍管理用のSilverlightアプリがほしいなーと思っています。画像や書籍の情報なんかを手軽に利用したいとなるとやっぱりAmazonかな、ということで、とりあえずAmazon Web Service API(Amazon AWS)をSilverlightで使ってみようと思います。

1.Amazon AWSのアクセスポリシー

Silverlightではそのアプリケーションがホストされたドメイン以外のサイトに対して通信を行う場合、クロスドメインの制限がかかるため、通信先のホストのルートディレクトリにあるclientaccesspolicy.xmlか、crossdomain.xml でそのサイトに対するアクセスが許可されている必要があります。Silverlightで他のドメインに通信をする場合は、まずはじめにこの部分を確認する必要があります。

くわしくは、CodeZineのこの記事を参照してくださいw。
Silverlightとサーバーサービスの連携

嬉しいことに、日本のamazon のWebサービスがホストされているhttp://ecs.amazonaws.jp/のcrossdomain.xmlを見ると、嬉しいことに次のように全サイトからのアクセスを許可してくれています。

Amazon Web Service の crossdomain.xml (http://ecs.amazonaws.jp/crossdomain.xml

<?xml version="1.0"?> 
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd"> 
<cross-domain-policy> 
   <allow-access-from domain="*" /> 
</cross-domain-policy> 

2.Amazon AWS Access Keyの取得と確認

Amazon AWSを利用するためには、Amazon AWSのサイトで、自分のAccess key IDとSecret Access keyを確認する必要があります。Amazon AWSのAccess KeyはこのAmason AWSのポータルサイトで確認できるので、自分のAmazonアカウントでログインして確認して下さい。Access key Idが公開鍵で、Secret Access keyが秘密鍵になります。この2つのキーをもとにAWSを使うための署名を作成します。Secret Access keyは外部に漏れないように厳重に管理しましょう。

Amazon AWSのポータルサイト⇒http://aws-portal.amazon.com/gp/aws/developer/account/index.html?action=access-key

Amazon AWSに登録していない人や、Amazonのアカウントを持っていない人やはこのあたりのサイトを参考にAmazon AWSのアカウントを取得してください。

Access Key IDの取得

3.書籍検索クエリの作成

Amazon AWSでは書籍の検索に限らず、Amazonで取り扱っている商品の検索や購入をProduct Advertising APIを使うことで行うことができます。今回はとりあえずSilverlightアプリケーションで書籍の検索を行ってみましょう。

書籍の検索は、次のクエリを利用します。(実際は1行です。)

http://ecs.amazonaws.jp/onca/xml?

AWSAccessKeyId=xxx&

Keywords=Silverlight&

Operation=ItemSearch&

ResponseGroup=Small&

SearchIndex=Books&

Service=AWSECommerceService&

Timestamp=2010-12-23T15%3A54%3A24Z&

Version=2009-03-31&

Signature=xxxxx"

リクエストの詳細はこのあたりで確認できます。クエリの詳細はこのあたりを確認して下さい。

⇒  Ajax Tower.jp 商品検索(ItemSearch)

また、Amazon AWSへのリクエスト2009年に改正され、リクエスト中にタイムスタンプや利用者のハッシュした署名を含める必要があります。署名の作成方法は下記のサイトで確認できます。

⇒ Ajax Tower.jp 認証(Timestamp及びSignature)

署名を作成するのは大変ですが、.NETで署名を作成するライブラリが、Amazonのデベロッパーフォーラムで公開されていますので、通常のパッケージに含まれるSignedRequestHelperクラスを使うのがいいでしょう。

Product Advertising API Signed Requests Sample Code – C# REST/QUERY

利用方法はこんな感じです。

var helper = new SignedRequestHelper(MY_AWS_ACCESS_KEY_ID, MY_AWS_SECRET_KEY, DESTINATION);
var param = new Dictionary<string, String>();
param["Service"] = "AWSECommerceService";
param["Version"] = "2009-03-31";
param["Operation"] = "ItemSearch";
param["Keywords"] = bookName.Text;
param["SearchIndex"] = "Books";
param["ResponseGroup"] = "Small";

var requestUrl = helper.Sign(param);
var request = new WebClient();
request.DownloadStringCompleted += (_s, _e) =>
{
    if (_e.Error != null)
    {
        MessageBox.Show(_e.Error.ToString());
        return;
    }
    MessageBox.Show(e.Result);

};
request.DownloadStringAsync(new Uri(requestUrl));
}

MY_AWS_ACCESS_KEY_IDとMY_AWS_SECRET_KEYには2で確認したキーを指定します。DESTINATIONには日本のAWSを利用するのでJPを指定します。

4.SignedRequestHelperの変更

困ったことに、SignedRequestHelperは.NET Frameworkを対象に書かれているため、Silverlightでは利用できないクラスを使っています。具体的には、SortedDictionaryクラスがそれです。特に、AWSのクエリはハッシュの作成のために、クエリの順番が特に重要なためです。しかし落胆することはありません、問題はキーの順番が保証されてさえいればいいのです。嬉しいことにSilverlightにはLINQがあります。とりあえず順序保証がされないDictonaryにパラメータを放りこんで、ハッシュを作成する時に並び替えてあげればいいのです。

/*
 * Consttuct the canonical query string from the sorted parameter map.
 */
private string ConstructCanonicalQueryString(IDictionary<string, string> sortedParamMap)
{
    StringBuilder builder = new StringBuilder();

    if (sortedParamMap.Count == 0)
    {
        builder.Append("");
        return builder.ToString();
    }

    // Dictionaryは順序保証されていないので、OrderByしてあげる
	// foreach (KeyValuePair<string, string> kvp in sortedParamMap)
    foreach (KeyValuePair<string, string> kvp in sortedParamMap.OrderBy(item => item.Key))
    {
        builder.Append(this.PercentEncodeRfc3986(kvp.Key));
        builder.Append("=");
        builder.Append(this.PercentEncodeRfc3986(kvp.Value));
        builder.Append("&");
    }
    string canonicalString = builder.ToString();
    canonicalString = canonicalString.Substring(0, canonicalString.Length - 1);
    return canonicalString;
}

4.XMLをパースする。

リクエストに対するレスポンスはこんなXMLです。

image

XMLのパースといえば、やっぱりここでも LINQ です。 DataGridに表示するためには、匿名型ではダメなので、検索結果というクラスを作って、パース結果をそのクラスに流し込んでいます。

    // Grid表示
    var xml = XElement.Parse(_e.Result);
    XNamespace ns = "http://webservices.amazon.com/AWSECommerceService/2009-03-31";
    var result = from item in xml.Descendants(ns + "Item")
                 select new 検索結果
                 {
                     Asin = item.Element(ns + "ASIN").Value,
                     Url = item.Element(ns + "DetailPageURL").Value,
                     Author = item.Element(ns + "ItemAttributes").Element(ns + "Author").Value,
                     Title = item.Element(ns + "ItemAttributes").Element(ns + "Title").Value,
                 };
    bookList.ItemsSource = result.ToList();

5.動かしてみる。

image

うごいた。後は受け取ったURLに含まれる情報からAmazonのサイトをWebブラウザーコントロールに表示市たいんですが、それはCodeZineの連載を見てください。多分2月ぐらいの回を乞うご期待です。

6.おまけ

とりあえずサンプルプロジェクトはここにおいておきます。

http://cid-b17f5fcd8095628b.office.live.com/self.aspx/%E5%85%AC%E9%96%8B/WebApplication2.zip

 

#追記

通りすがりさんのコメントを参考に、ConstructCanonicalQueryStringメソッドでのソート時に、大文字小文字を区別してソートするようにしました。(2010/12/30)

カテゴリー:Silverlight タグ: