はじめに
今回はネットワークアクセスを行うMap Appを作ってみましょう。Silverlightアプリケーションで画像やWebページダウンロードなどのWebアクセスは、.NET Frameworkと同様にSystem.Net.WebClientクラスを使用すると簡単にできますが、Map App SDKには、ネットワークアクセス用の機能が提供されています。クラスが用意されているだけでドキュメント類は皆無なのですが、今回はこれを使用してネットワークアクセスに挑戦してみましょう。
Webアクセス
NetworkManagerContract
ネットワークアクセスにはNetworkManagerContractを使用します。このContractで提供される機能を使用すると、WebClientに似たPrioritizedWebClientクラスを使えます。特徴は、名前にあるようにWebアクセスのとき優先順位を設定可能になっています。地図の隠れている周辺部分の情報を低優先で先行して情報を取得しておくなどの用途が想定されているのではないかと思われます。また、このContractを使用するとネットワークアクセスが発生していないアイドル状態を知ることができます。
コードは、これまでと同様にContractの機能を使用するため、次のようにプロパティを宣言します。
プラグインクラス
上記のプロパティの宣言を含む、今回作成する プラグインの元となるコードは次のようになります。これまでの内容を参考にプラグインクラスとレイヤークラスを作成してください。
以上のコードを元に、追記していきます。
PrioritizedWebClient
それでは、PrioritizedWebClientクラスを使ってWebアクセスしてみましょう。PrioritizedWebClientクラスは直接インスタンスを生成するのではなく、CreatePrioritizedWebClientメソッドによって取得します。
Webページを文字列としてダウンロードするには、PrioritizedWebClientクラスのDownloadStringAsyncメソッドを使います。優先順位を指定する場合、Priorityプロパティを使用します。
非同期メソッドのため、ダウンロードが完了したときのメソッドを用意する必要があります。ここでは、前回に紹介したダイアログを使ってダウンロードした文字列を表示するようにしています。
Webページダウンロード部分をメソッド化して、以上のコードをまとめると以下のようになります。
作成したDownloadStringメソッドを、Activateメソッド内で呼んでみましょう
そして、プラグインを実行してみます。結果は図1のようになったのではないでしょうか。
エラーが発生し例外の内容が表示されてしまったのではないかと思います。Silverlightアプリケーションでは、アプリケーションとは異なるドメインへ(ここでは、アプリケーションはwww.bing.com、アクセスしようとした先は、gihyo.jp)のアクセスは、セキュリティのため許可がない場合できません。
異なるドメインへのアクセス
異なるドメイン間でSilverlightアプリケーションからWebサービスなどのコンテンツにアクセスできるようにするためには、アクセス先のサーバー側で許可する必要があります。つまりMap Appのプラグインの作りをどうこうして可能なものではありません。接続先のWebサービスのサーバーがアクセス許可されているかの確認、または、自分でMap Appと連携するサービスを作成する場合に、ここでの作業が必要になります。
アクセス許可の方法は、clientaccesspolicy.xmlというファイルをサーバー側に配置します。すべてのクライアント(Silverlightアプリケーション)からアクセスを許可する場合のファイルの内容は次のようになります。
このclientaccesspolicy.xmlファイルを、クライアントからのアクセス先のドメインのルート、たとえばgihyo.jpの場合は、http://gihyo.jp/clientaccesspolicy.xmlでアクセスできる場所に配置します。実際にhttp://gihyo.jpにあるファイルを操作できませんので、独自ドメインの使用できるレンタルサーバーなどを用意して、ファイルを配置し試してみてください。
Silverlightアプリケーションは、ネットワークアクセスが発生したとき、このファイルの存在を確認し、その内容に基づいて許可されているアクセスを行います。先の例では、gihyo.jpには、ファイル自体が存在しない、またはアクセス許可されていなかったということですね。
残念ながらRSSフィードやWeb APIなどを提供しているサーバーなどでも、すべてのSilverlightアプリケーションに対してアクセス許可がされているサーバーはほとんどないのが現状です。Map Appから公開されているWeb APIなどを利用するには中継するサーバーを自前で用意する必要がありそうです。
さて、Bing MapsのWeb APIのアクセス先であるhttp://dev.virtualearth.netではclientaccesspolicy.xmlがあり、アクセス可能です。先ほどのコードのアクセス先をhttp://dev.virtualearth.netに変更して実行すると、正しくWebページの内容が取得できています(図2)
Adobe Flashでも同様の仕組みがあり[1]、その方法もSilverlightでは対応しています。その場合、crossdomain.xmlというファイルを使用します。
外部XMLファイルからプッシュピンの追加
第2回では、県庁所在地にプッシュピンを追加するMap App(図3)を作成しましたが、そのとき県庁所在地の情報はXMLファイルをプラグインのアセンブリにリソースとして埋め込み参照していました。
今回紹介した方法で、XMLファイルを外部のWebサーバーに配置して、プラグインではファイルをダウンロードしプッシュピンを配置するようにしてみましょう。コードは最初に示したものを編集します。第2回ではパネルも使用していましたが今回は省略しています。
県庁所在地の情報サーバー
Webサーバー側に必要な作業は次の通りです。
- 独自ドメインのWebサーバーの用意
- clientaccesspolicy.xmlファイルの配置
- 県庁所在地情報のXMLファイルの配置
サーバー側はドメインのルートにファイルを配置できる必要があります。そして、clientaccesspolicy.xmlファイルを参照できるようにしておきましょう。
県庁所在地の情報を書いたXMLファイルは以前と同じ内容のものです。下記のような情報を記述したファイルを、同じドメインの任意のディレクトリに配置し、HTTPで参照できるようにしましょう。
以上でWebサーバー側の準備はできました。今回は静的なXMLファイルにアクセスしていますが、PHPやASP.NETなどを使用してURLにパラメーターを指定して動的な結果を返すことができれば、ユーザーの表示している場所や操作によって表示内容を変えるMap Appも作成可能ですね。
プラグインの変更
プラグイン側を、用意したWeb上のXMLファイルにアクセスするように変更します。
先ほどはPrioritizedWebClient クラスのDownloadStringAsyncメソッドを使用して文字列としてダウンロードしていました。これでも問題ありませんが、次はストリームを取得するOpenReadAsyncメソッドを使って書いてみましょう。
特に難しいところはありませんね。実際にストリームを処理するメソッドは次のようになります。
最後に作成したOpenReadメソッドを呼ぶようにActivateメソッド部分を書きかえて、プラグインを実行してみましょう。結果は図4のようになります。きちんと動作したでしょうか?
おわりに
今回はMap AppからWebアクセスについて紹介しました。実際にMap Appを作成する場合、天気予報など時間によって変化する情報を扱う場合は、外部にMap AppがアクセスするWebサーバーを用意して、Webアクセスが必要になってくると思います。また、サードパーティの情報取得に使用するだけでなく、経緯度から住所や画像などを取得するBing Mapsで提供されているWeb APIを利用する場合にもこのようにアクセスして使います。このWeb APIについてはいずれ連載で機会があれば紹介したいと思いますが、次回は、Map Appの予定です。