はじめに
今回はSilverlightでBing APIを使ってみましょう。Silverlightを使用すれば、Webアプリケーションだけでなくクライアント アプリケーションも作成可能です。Silverlightについては詳しく説明しませんが、実行までの手順を初めての方でも理解できるよう紹介しています。一緒にBing APIによる検索アプリケーションを作ってみましょう。
前回 までのjQueryでBing APIを利用したときは、次のようなURLにアクセスしてJSON形式のデータを取得していました。
http://api.bing.net/json.aspx?
AppId=AppId &
Version=2.2 &
Market=ja-JP &
Query=Windows &
Sources=Web
jQueryの場合と同様の方法をSilverlightでも記述できますが、Bing APIにはHTTPとXMLをベースとしたSOAPというプロトコルのサービスも提供されています。Silverlightから利用する場合は、SOAPのほうが便利です。今回はこのSOAPのBing APIを利用します。
開発環境
はじめに開発環境についてです。Silverlightでの開発は次の環境が必要です。あらかじめインストールを行ってください。
無償のVisual Web Developer Express 2010 Express とSilverlight 4 Toolsの組み合わせでも開発できます。Visual Web DeveloperはMicrosoft Web Platform Installer 内に含まれています。
またデザイナツールのExpression Blend 4 もあるとよいですが、今回は使用しません。
ライブラリーのインストール
Silverlightアプリケーション開発には必須ではありませんが、今回のアプリケーションでは、Reactive Extensions for .NETというライブラリーを使用して非同期処理を行っています。DevLabs から「Rx for Silverlight 4」をダウンロードしインストールを行ってください(Webページの右側の「Get Rx」にダウンロードのボタンがあります) 。
Bing APIサービスの参照
それでは、Bing APIをSilverlightで利用してみましょう。まず、Visual Studioでプロジェクトを作成して、サービスの参照という手順を踏んで、Bing APIを利用するクラスを自動生成するところまで説明します。
プロジェクトの作成
まず、Visual StudioでSilverlightアプリケーション プロジェクトを作成します(図1 ) 。ここではプロジェクト名を「BingApiSample」にしています。また、この連載ではVisual Basicを使用します。
図1 Silverlightアプリケーション プロジェクトの新規作成
OKボタンをクリックすると、図2 のようにSilverlightアプリケーションを新しいWebサイトでホストするか聞かれますので、図のようにそのままOKボタンをクリックします。
図2 Silverlightアプリケーションを新しいWebサイトでホスト
以上で新しい Silverlight アプリケーション プロジェクトと、そのアプリケーションを表示するためのWebアプリケーション プロジェクトが作成されました。この後、特に指定がなければ扱うプロジェクトはSilverlightアプリケーション プロジェクトのほうです。
最初にインストールしたライブラリーも使用できるようプロジェクトに参照を追加しておきましょう。Visual Studioプロジェクト メニューの参照の追加から、次の3個のコンポーネントを追加します(図3 ) 。
System.CoreEx
System.Observable
System.Reactive
図3 参照の追加
サービス参照の追加
SOAPによるWebサービスの利用は、特定のURLへリクエストをXML形式のデータで送信し、レスポンス データをXML形式で受信することで行います。HTTPで送受信するコードを直接記述してもよいですが、SOAPではWebサービスにどのようなメソッドやどのようなデータを送受信すればよいかが定義されています。そのため、Visual Studioを利用すると、Webサービスにアクセスするクラスの自動生成が可能です。
プロジェクト メニューからサービス参照の追加を選択します。開いたウィンドウにあるアドレス欄に以下のURLを入力します。
http://api.bing.net/search.wsdl?AppID=AppID &Version=2.2
このアドレスがBing APIのサービスを定義しているURLです。AppIDパラメーターにはApplication ID(AppID)を指定してください。AppIDの取得は第19回 で紹介しています。
移動ボタンをクリックするとBing APIで提供されているサービス内容が確認できます(図4 ) 。Searchというメソッドのみ定義されていることがわかります。名前空間に適当な名前を入力しOKボタンをクリックして、サービス参照を追加します。ここでは名前空間を「ServiceReference」にしています。
図4 サービス参照の追加
以上で、Bing APIにアクセスするBingPortTypeClient というクラスが作成されています。
Webサイトの検索
次にBing APIを利用してWebサイトを検索します。検索クエリーを入力と、結果の表示をするために画面を作成してから、コードを記述します。
画面の作成
SilverlightではXAMLと呼ばれるXMLベースの言語によって画面が構成されています。今回は直接XAMLを記述して画面を作成します。ソリューションエクスプローラーからMainPage.xamlを選択しデザイナーを表示します(図5 ) 。
図5 デザイナーの表示
※図では、この後に示すコードを入力済みです。
ここに、テキストボックス(TextBox) 、ボタン(Button) 、リストボックス(ListBox)を追加します。それぞれ検索クエリーの入力、検索の実行、結果の表示に使用します。XAMLのコードは次のようになります。はじめから記述されている要素部分を下記のコードと置き換えます。
<Grid x:Name = "LayoutRoot" Background = "White" >
<Grid.RowDefinitions>
<RowDefinition Height = "Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width = "Auto" />
</Grid.ColumnDefinitions>
<TextBox x:Name = "QueryTextBox" Margin = "5" />
<Button x:Name = "SearchButton" Grid . Column = "1" Margin = "5" Width = "80"
Content = "検索" />
</Grid>
<ListBox x:Name = "ResultListBox" Grid . Row = "1" Margin = "5" />
</Grid>
この後にも編集しますが、ひとまず画面の作成は以上です。まだ何も動作しませんが、デバッグ メニューからデバッグの開始をすると、図6 のようにWebアプリケーションが実行されます。
図6 実行結果 画面の確認
コードの記述
続いてAPIの呼び出しなどを行うコードを記述します。ソリューションエクスプローラーからMainPage.xaml.vbを開きます。名前空間の記述を省略できるよう、以下のコードを先頭にまず記述しておきましょう。
Imports BingApiSample . ServiceReference
次に、検索処理と結果の表示を行うSearch メソッドを作成します。MainPageクラス内に次のコードを追記してください。
Private Sub Search ( ByVal query As String )
If query = "" Then
Exit Sub
End If
End Sub
ボタンをクリックしたとき、Searchメソッドを実行します。次のようにコンストラクタでClickイベントの関連付けを行っておきます。
Public Sub New ()
InitializeComponent ()
AddHandler SearchButton . Click , Sub () Search ( QueryTextBox . Text )
End Sub
検索処理の手順は次のように行います。必ずしもこうしなければならないというものではありません。
BintPortTypeClientオブジェクトの生成
検索が完了したときの処理を定義(リストボックスにレスポンス内容を表示)
検索リクエストの作成
検索API呼出し
まずBintPortTypeClientオブジェクトを生成します。自動生成されたクラスでしたね。
Dim client = New BingPortTypeClient
APIの呼出しは非同期で行います。レスポンスを受信(検索結果を取得)したとき、BingPortTypeClientオブジェクトのSearchCompletedイベントが発生します。その時の処理を以下のように記述します。ここでは単にListBoxのItemsSourceプロパティに検索結果のオブジェクトをそのまま指定しています。
Observable . FromEvent ( Of SearchCompletedEventArgs )( client , "SearchCompleted" ) _
. Take ( 1 ) _
. Subscribe (
Sub ( e )
If e . EventArgs . Error Is Nothing Then
Dim result = e . EventArgs . Result
ResultListBox . ItemsSource = If ( result . Web IsNot Nothing , result . Web . Results , Nothing )
End If
End Sub )
リクエストの作成は次のようになります。AppIDや検索クエリーなど検索の全般的な設定を指定は、SearchRequest オブジェクトを使用し、Webサイトの検索に関するリクエストは、WebRequst オブジェクトを使用します。Webサイト検索の場合、SearchRequestオブジェクトのSources プロパティにSourceType.Web を指定し、Web プロパティにWebRequestオブジェクトを指定します。
Dim request = New SearchRequest With {
. AppId = " AppID " ,
. Market = "ja-JP" ,
. Query = query ,
. Sources = { SourceType . Web },
. Web = New WebRequest With {
. Offset = 0 ,
. Count = 10 }
}
最後に、検索を実行します。
client . SearchAsync ( request )
ここまでを実行してみましょう。テキストボックスにクエリーを入力し検索ボタンをクリックすると図7のようになるかと思います。
図7 実行結果 検索結果の表示
リストボックスにWebサイトの検索結果(WebResult オブジェクト)のコレクション(コードではe.EventArgs.Result.Web.Results)を追加しただけですので、WebRe
sultオブジェクトが持つWebサイトのタイトルや説明は正しく表示されません。次は正しく結果が表示されるようデザイナーでXAMLをもう一度編集しましょう。
デザインの編集
リストボックスに表示される項目(ListBoxItem)のデザインを編集します。<ListBox>要素の部分を次のように変更してください。
<ListBox x:Name = "ResultListBox" Grid . Row = "1" Margin = "5"
ScrollViewer . HorizontalScrollBarVisibility = "Disabled" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin = "0 0 0 10" >
<HyperlinkButton NavigateUri = "{Binding Url}" TargetName = "_blank" >
<TextBlock Text = "{Binding Title}" />
</HyperlinkButton>
<TextBlock Text = "{Binding Description}" TextWrapping = "Wrap" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
検索結果のデータの表示方法は、Silverlightのデータバインディングと呼ばれる方法を用いています。上記コードでは「Text={Binding Title}」のように記述することで、TextBlockのTextプロパティにListBoxのItemsSourceプロパティに指定したコレクションの各アイテム(WebResultオブジェクト)のTitleプロパティの値を指定しています。
もう一度、実行して確認すると図8 のようになります。
図8 実行結果 リストボックスの項目の編集
以上で、Webサイトの検索ができるようになりました。XAMLを編集することで自由に見た目を変更できます。
Webサイト検索結果のプロパティ
使用したWebResultオブジェクトのプロパティは、Title・Url・Descriptionプロパティのみでしたが、WebResultオブジェクトには次のプロパティが用意されていますので、活用してみてください。
名前
説明
DateTime
最終更新日またはクロールした時間
例: 2011-03-30T07:20:00Z
Description
説明(検索語が含まれるWebページの文章の一部)
DeepLinks
Webサイトに含まれるリンク(DeepLinkオブジェクト)のコレクション
各アイテムはTitleとUrlプロパティを持っています。
DisplayUrl
表示用のURL
SearchTags
検索用タグ(SearchTagオブジェクト)のコレクション
<meta>タグのname属性が「search.」ではじまるとき、nameとcontent属性の値が、NameとValueプロパティで参照できます。
Title
Webサイトのタイトル
Url
WebサイトのURL
CacheUrl
WebサイトのキャッシュのURL
ただし、これらのプロパティはかならず含まれているわけではありません。次のようにXAMLを編集すると、すべての値を確認できます。
<ListBox x:Name = "ResultListBox" Grid . Row = "1" Margin = "5"
ScrollViewer . HorizontalScrollBarVisibility = "Disabled" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin = "0 0 0 10" >
<HyperlinkButton NavigateUri = "{Binding Url}" TargetName = "_blank" >
<TextBlock Text = "{Binding Title}" />
</HyperlinkButton>
<TextBlock Text = "{Binding Description}" TextWrapping = "Wrap" />
<TextBlock Text = "{Binding DateTime}" />
<TextBlock Text = "{Binding DisplayUrl}" />
<TextBlock Text = "{Binding CacheUrl}" />
<ListBox Margin = "10 0 0 0" ItemsSource = "{Binding DeepLinks}" >
<ListBox.ItemTemplate>
<DataTemplate>
<HyperlinkButton NavigateUri = "{Binding Url}" TargetName = "_blank" Content = "{Binding Title}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ListBox Margin = "10 0 0 0" ItemsSource = "{Binding SearchTags}" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation = "Horizontal" >
<TextBlock Text = "{Binding Name}" />
<TextBlock Text = "{Binding Value}" Margin = "5 0 0 0" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
送受信内容の確認
ここで、必須の内容ではありませんが、Bing APIの呼出し時のBing APIサーバーとの通信内容を見てみたいと思います。HTTPの通信内容を見るのにFiddler2 というツールを使用します。
確認方法は簡単です。Fiddler2を起動後、作成したSilverlightアプリケーションで検索を実行します。すると、キャプチャリングした通信内容が表示されます(図9 ) 。
図9 Fiddler2でBing API呼出しをキャプチャリング
Visual Studioを使用したため実際の通信処理の部分は隠ぺいされた形になっていましたが、実際に通信内容を確認すると、http://api.bing.net/soap.asmxにアクセスし、リクエスト・レスポンスデータがXML形式でやりとりされていることがわかります。
画像の検索
作成したSilverlightアプリケーションのコードを変更して、画像の検索をしてみましょう。
まず、MainPage.xaml.vbのSearchメソッド内の変更です。API 呼出し完了したとき、Web.Resultsコレクションではなく、Image.ResultsコレクションをListBoxのItemsSourceに指定します。
Observable . FromEvent ( Of SearchCompletedEventArgs )( client , "SearchCompleted" ) _
. Take ( 1 ) _
. Subscribe (
Sub ( e )
If e . EventArgs . Error Is Nothing Then
Dim result = e . EventArgs . Result
ResultListBox . ItemsSource = If ( result . Image IsNot Nothing , result . Image . Results , Nothing )
End If
End Sub )
リクエストの作成も次のようにImageRequest オブジェクトとSourceType.Image を指定するようにします。
Dim request = New SearchRequest With {
. AppId = " AppID " ,
. Market = "ja-JP" ,
. Query = query ,
. Sources = { SourceType . Image },
. Image = New ImageRequest With {
. Offset = 0 ,
. Count = 10 }
}
次は、MainPage.xamlの変更です。<ListBox>要素を次のように変更します。
<ListBox x:Name = "ResultListBox" Grid . Row = "1" Margin = "5"
ScrollViewer . HorizontalScrollBarVisibility = "Disabled" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin = "0 0 0 10" >
<HyperlinkButton NavigateUri = "{Binding Url}" TargetName = "_blank" >
<TextBlock Text = "{Binding Title}" />
</HyperlinkButton>
<Image Source = "{Binding Thumbnail.Url}" Width = "{Binding Thumbnail.Width}" Height = "{Binding Thumbnail.Height}" HorizontalAlignment = "Left" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
画像の検索結果特有のThumbnailオブジェクトを<Image>要素で表示するように変更しました。実行結果は図10 のようになります。
図10 実行結果 画像の検索
複数の対象を検索
Bing APIでは、Webサイトと画像などを1回のリクエストで同時に検索できます。ここでは、Webサイト、関連キーワード、画像を一度に検索して表示してみましょう。
同時に検索するには、SearchRequest オブジェクトのSourcesプロパティに複数の種類を指定するだけです。MainPage.xaml.vbのリクエスト作成部分は次のようになります。
Dim request = New SearchRequest With {
. AppId = " AppID " ,
. Market = "ja-JP" ,
. Query = query ,
. Sources = { SourceType . Web , SourceType . RelatedSearch , SourceType . Image },
. Web = New WebRequest With {
. Offset = 0 ,
. Count = 10 },
. Image = New ImageRequest With {
. Offset = 0 ,
. Count = 10 }
}
関連キーワードのオプションはないため、WebRequestやImageRequestに相当するものはありません。
次に、XAMLを編集して結果を同時に表示できるようにしましょう。<ListBox>要素部分を次のコードに置き換えます。ListBoxを3個、横に並べています。
<Grid Grid . Row = "1" >
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ListBox x:Name = "KeywordResultListBox" Margin = "5" ScrollViewer . HorizontalScrollBarVisibility = "Disabled" >
<ListBox.ItemTemplate>
<DataTemplate>
<HyperlinkButton NavigateUri = "{Binding Url}" Content = "{Binding Title}" TargetName = "_blank" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ListBox x:Name = "WebResultListBox" Grid . Column = "1" Margin = "5" ScrollViewer . HorizontalScrollBarVisibility = "Disabled" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin = "0 0 0 10" >
<HyperlinkButton NavigateUri = "{Binding Url}" Content = "{Binding Title}" TargetName = "_blank" />
<TextBlock Text = "{Binding Description}" TextWrapping = "Wrap" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ListBox x:Name = "ImageResultListBox" Grid . Column = "2" Margin = "5" ScrollViewer . HorizontalScrollBarVisibility = "Disabled" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin = "0 0 0 10" >
<HyperlinkButton NavigateUri = "{Binding Url}" Content = "{Binding Title}" TargetName = "_blank" />
<Image Source = "{Binding Thumbnail.Url}" Width = "{Binding Thumbnail.Width}" Height = "{Binding Thumbnail.Height}" HorizontalAlignment = "Left" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
MainPage.xaml.vbに戻って、API 呼出し完了時の処理を変更します。3種類の検索結果をそれぞれのListBoxのItemsSourceプロパティにしているだけです。
Observable . FromEvent ( Of SearchCompletedEventArgs )( client , "SearchCompleted" ) _
. Take ( 1 ) _
. Subscribe (
Sub ( e )
If e . EventArgs . Error Is Nothing Then
Dim result = e . EventArgs . Result
KeywordResultListBox . ItemsSource = If ( result . RelatedSearch IsNot Nothing , result . RelatedSearch . Results , Nothing )
WebResultListBox . ItemsSource = If ( result . Web IsNot Nothing , result . Web . Results , Nothing )
ImageResultListBox . ItemsSource = If ( result . Image IsNot Nothing , result . Image . Results , Nothing )
End If
End Sub )
実行結果は図11 のようになります。
図11 実行結果 複数の対象を検索
おわりに
今回のアプリケーションを公開する場合は、Webアプリケーションプロジェクトにある次の3個のファイルをWebサーバー(Windows Serverである必要はありません)上に配置するだけです。
ClientBn/BingApiSample.xap
BingApiSampleTestPage.html
Silverlight.js
Webサーバーによっては、xapファイルが公開できるようMIME Typeをapplication/x-silverlight-appに設定する必要があります。
また、Silverlightアプリケーション プロジェクトのプロパティで、Silverlightタブにある「アプリケーションのブラウザー外実行を有効にする(B)」を有効にすると(図12 ) 、クライアントPCにアプリケーションのインストールができるようになります(図13 ) 。
図12 ブラウザー外実行の有効
図13 Silverlightアプリケーションのインストール
これが冒頭で紹介した、Silverlightのクライアント アプリケーションです。
今回は以上です。いかがでしたでしょうか。次回もSilverlightによるBing APIの利用を紹介する予定です。