Silverlight2 Beta 2のcrossdomainアクセスについて

めっちゃはまった。そしてゲイツぶっとばす。と3回はつぶやいた。

えっと、、、先日Silverlight 2 Beta 2がリリースされました。

昨日、「:【RIA開発セミナー】プロデューサー、ディレクター必見 Silverlightによる開発のおさえどころはココだ!」を聞いたのですが、冠の通りdeveloperが聞く内容ではなかったです。「開発のおさえどころ」ではなく、「プロジェクトのおさえどころ」が正しかったのではないかと・・・
それはさておきタイトルのSilverlightのcrossdomainアクセスの話です。

Silverlightは一応クライアント側で動作しますが、crossdomainアクセスに関してはAjaxやflashの用に制限がかかっています。

制限のかけ方については基本的にはflashに似ていて、アクセスされる側がpolicyファイルを置くと、Silverlight Runtimeがそのファイルを読んで対応します。

今回、実際にcrossdomainでアクセスしたいことがあり、以前なにかで、Adobe flashのpolicyファイル(crossdomain.xml)にも対応していると読んだので、crossdomain.xmlを置いて、Beta 2のドキュメントにあったサンプルコードを貼り付けて動かしてみました。

が、アクセスできません。いろいろ中身を変えてみてもダメ。あきらめてドキュメントをまじめに読みました。超適当な訳による簡易メモを下記に載せます。

Silverlightは二つのpolicyファイルに対応する
Flash policy file:
– crossdomain.xml
– System.NetのWebClientとSystem.Net.HTTPクラスで使われる
Silverlight policy file:
– clientaccesspolicy.xml
– System.Net.Socketsのソケットクラス達で使われる
アクセスの許可を調べるためにSilverlightランタイムがこのpolicyファイルをダウンロードする。いずれもターゲットdomainのルート直下を探す。

WebClient/HTTPのときはHTTPプロトコルでpolicyファイルのダウンロードを試みる。先にSilverlight policy file(clientaccesspolicy.xml)のダウンロード試みて、なければFlash policy file(crossdomain.xml)のダウンロードを試みる。

socketからのリクエストならTCPプロトコルでSilverlight policy file(clientaccesspolicy.xml)のダウンロードを試みる。

policyファイルがなかったりパースできないときは接続はできない。

いくつか注意するところがありました。

  1. Silverlightのpolicyファイルを使うときはcrossdomain.xmlではなくclientaccesspolicy.xmlで保存しないといけないということ。
  2. crossdomain.xmlとclientaccesspolicy.xmlが両方あった場合はclientaccesspolicy.xmlが優先されるということ。
  3. ソケットクラスによるアクセス時にはcrossdomain.xmlは使われないということ。

とりあえず最初の失敗はドキュメントのサンプル(silverlight policy fileの書式)をcrossdomain.xmlで保存してしまったことにありました。

というわけでcrossdomain.xmlをclientaccesspolicy.xmlにリネームして試しました。

が、やっぱりアクセスできません。何故だ。何故なんだ。

問題を切り分けたいのですが、困ったことにexceptionも発生しないし、エラーとか何も教えてくれません。WebClient.DownloadStringAsyncを使っていたのですが正常系のフローで空文字が返ってきます。これだとcrossdomainアクセスに失敗しているのか、成功しているんだけど404なのか、いや200だけど本当に空ページなのか、、、全然わかりません。ブラウザでそのurlを開いてみてもページは見えるし、clientaccesspolicy.xmlも見えるし。

そこでFlash policy fileを試してみることにして、とりあえずテストなので全アクセス許可のcrossdomain.xmlを拝借して置いて、clientaccesspolicy.xmlを退避させてみたところ見事に接続できるようになりました。clientaccesspolicy.xmlとcrossdomain.xmlの両方を置いたらやっぱり接続できないのでようやくclientaccesspolicy.xmlの内容に問題があるとわかりました。

しかし、中身を見てもやっぱりどこが悪いかわかりません。ひょっとしてBeta 2のバグなのか?と思いForumを覗いてみることに。しかし、ピンとくるスレッドがありません。一つBeta 2になってからallow-from要素のhttp-request-headers属性が必須になったという話があったのですが、それはちゃんと入れてるし、っていうかBeta 2のドキュメントのサンプルを使ってるわけだし。。。

まさか日本語環境だけで起きる問題?
とにかくわからないのでForumに投稿しようかと思っていたとき、あるスレッドで全アクセス許可のサンプルコードが貼り付けられていたので、間違いさがしのつもりでそれをペーストしてみました。すると間違いどころか行が増えました。

参考にしたドキュメントのサンプルコード

<?xml version="1.0" encoding="utf-8"?>
<access-policy>
<cross-domain-access>
<allow-from http-request-headers="*">
<domain uri="*"/>
</allow-from>
<grant-to>
<resource path="/api" include-subpaths="true"/>
</grant-to>
</cross-domain-access>
</access-policy>

こっちがフォーラムで見つけたサンプル

<?xml version="1.0" encoding="utf-8"?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers="*">
<domain uri="*"/>
</allow-from>
<grant-to>
<resource path="/" include-subpaths="true"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>

resoure pathは”/”に修正して使っていたので異なる点は、cross-domain-access要素の下にpolicy要素があるか、ないか。ドキュメントを見るとサンプルコード4つのうち2つがこのpolicy要素が抜けています。

policy要素を入れたところ接続できるようになったのは言うまでもありません。ゲイツぶっとばす。と3回つぶやいたあとにマイクロソフトのドキュメントチームにフィードバックを送りました。