ADO.NET Data Servicesについて、驚愕の事実
正確には「SilverlightでのADO.NET Data Service クライアントについて、驚愕の事実」なんですが、どちらにしろ驚愕でした。
なんと、クロスドメインのアクセスがサポートされていなかったのです!!もっと正確には結果的にクロスドメインが使えないって感じなのですが詳細にみていきましょう。
テスト用のプロジェクトの作成
とりあえず、テスト用の以下のプロジェクトを作成します。
- Silverilght用プロジェクト
- Silverlightホスト用Webアプリケーションプロジェクト
- ADO.NET Data Services用Webアプリケーションプロジェクト
以下のような感じ。
いろんな説明をすっ飛ばして、サービスとかクライアントとかは既に作ってます。
Silverlightからデータサービスにアクセス
以下のように普通にデータサービスにアクセスします。
NorthwindEntities context = new NorthwindEntities(new Uri("http://localhost:49301/NorthwindService.svc")); context.Customers.BeginExecute(result => { var customers = context.Customers.EndExecute(result).ToList(); MessageBox.Show(customers.Count.ToString()); },null);
なんてことはない普通のコードです。
実行
Webアプリプロジェクトをスタートアップに設定して、実行してみます。
例外が出ました。。
もう少し詳細にみたいので、スタックトレースを確認してみます。
ん?この4行目にある
....ScriptXmlHttpRequest.Open(.....)
ってなんですか??
もしかして、JavaScriptのXmlHttpRequset使ってます??
XmlHttpRequestを使っているか確認
XmlHttpRequestを使っているか確認してみます。
まずは、Serviceのプロジェクトに Silveright をホストするように設定して、そこからデバックを実行します。こうすることでクロスドメインではなくなるので、正常に動作するはずです。
で、動かすと...動きました。
Firebug で XmlHttpRequestが使われているか見てみます。
使われていました。
ということで、JavaScript の XmlHttpRequest は現状クロスドメインをサポートしていないので、結果的に Silverlight の ADO.NET Data Services のクライアントもクロスドメインでは動かないってことになります。
ちなみに、IE8 にしてみると、こいつは動いてしまいました。。。別のポートでもドメインは一緒って仕様に変わったのかな?? IE7 じゃ動かないのに。。。
理由を考えてみる
ここからは完全に推測ですが、なぜ JavaScript の XmlHttpRequest が使われているのですが、以下らへんに理由があるのかなぁと。
解説
Method プロパティに設定できるメソッドは GET と POST だけです。その他の HTTP 1.1 または HTTP 1.0 のプロトコル動詞 (HEAD、PUT、DELETE、TRACE、OPTIONS など) を設定すると、NotSupportedException 例外がスローされます。
http://msdn.microsoft.com/ja-jp/library/system.net.httpwebrequest.method(VS.95).aspx
ADO.NET Data Service は PUT も DELETE も使うので、そもそも WebRequest だけでなく Silverlight 自体がGET/POSTしかサポートしていないのであれば、分からんでもないです。更新が出来ない ADO.NET Data Service ってかなりおかしい話ですからねぇ。
回避方法を考えてみる
まぁ、順当にいけばサーバーにプロキシ用のサービスを作って、そこでつなげってことになるんでしょうが、それはそもそもADO.NET Data Services のうまみを逃してしまう。クライアントでクエリが書けて一発でデータ取得から更新から出来てしまうのに、それが出来なくなるなんて。
で、Flash(ActionScript)を使うなんてどうでしょう??まったくテストしてなくって単なるアイデアベースですが。以下を見るに何となくいけそうです。
http://livedocs.adobe.com/flex/3_jp/langref/flash/net/URLRequestMethod.html
JavaScript を仲介役にして、Silveright と Flash を繋いでやり取りするイメージです。URLとかリクエストのボディとかを自分で作ってやる必要があるので、大変っちゃー大変であまり現実的でないのですが、出来ないことはないかと。
Silveright 3 ではこのあたり解決してくれていることを非常に期待します。