ASP.NET Web API 2 CORS サポートについて
ASP.NET Web API 2 の新機能の 1 つとして CORS サポートがあります。
クロスドメイン通信についてちゃんと分かっていなかったので、
・クロスドメイン通信
・CORS
・ASP.NET Web API の CORS サポート実装
についてまとめたいと思います。
ASP.NET 公式サイトによる説明はこちら:
Enabling Cross-Origin Requests in ASP.NET Web API
CodePlex - Documentation>Specs>CORS support for ASP.NET Web API
クロスドメイン通信について
クロスドメイン通信を行うには、JSONP を使うか、CORS に従う必要があります。
CORS を利用するには、ブラウザ・サーバーの双方が CORS に対応している必要があり、ブラウザの種類やバージョンにより、対応・非対応があります。
使用する通信 API も異なっています(XMLHttpRequest か XDomainRequest になる)。
この辺の違いがとても複雑。
CORS(Cross-Origin Resource Sharing)によるクロスドメイン通信の傾向と対策
XDomainRequest と XMLHttpRequest level 2 の 違い
jQuery で Ajax(クロスドメイン) ブラウザ対応まとめ
IE 8, 9 あたりについて
よく、IE 8, 9 のクロスドメイン通信を可能にする jQuery プラグインとかありますが、
それは、XMLHttpRequest を利用する”jQuery.ajax(...)”で CORS が使えないためです。
jQuery プラグインにより、内部で XDomainRequest を使うことでクロスドメイン通信を行うようにしたりしています。
(IE 8, 9 は、XMLHttpRequest での CORS に対応しておらず、IE 10 から対応。)
XMLHttpRequest と XDomainRequest のどちらを利用するにしろ、ブラウザ・サーバーの双方が CORS に対応しなければクロスドメイン通信を行うことができません。
なので、「ASP.NET Web API 2 が CORS をサポート」というのは、必ずしも「今までできなかったブラウザでクロスドメイン通信が可能になる」とイコールにはならないです。
CORS とは
CORS の仕組みについては、
CORS(Cross-Origin Resource Sharing)によるクロスドメイン通信の傾向と対策
CORS(Cross-Origin Resource Sharing)について整理してみた
が大変わかりやすいです。
上記サイトを参考に、CORS に必要な HTTP メッセージのやりとりを図にまとめました。
赤太文字で書いてある部分が、通常とは異なる項目、CORS 対応に必要になる項目です。
ブラウザから送信する HTTP メッセージについは、CORS に対応しているブラウザが調整してくれます。Web 開発者が気にするべきところは、図の「WebService」のサーバー側が送信する HTTP レスポンスです。(そこが、ASP.NET Web API 2 の CORS サポートに関わる部分です。)
CORS には通信パターンが 2 種類あります。
1 つは、通常の Web API とほぼ変わらぬ方法。
2 つは、リクエストを送信する前に「こんなリクエスト送るね」と一度確認する方法です。
2 つめの最初のリクエストメソッドが、「OPTIONS」になっているのに注目。
どちらの通信パターンを行うかは、クロスドメイン通信で行いたい Web API のリクエストの内容によります。(GET 通信は 1 つめの方法で良いけど、PUT 通信は 2 つめの方法じゃないと駄目ーとか、いろいろ条件がある。)
「WebService」側では、いろいろヘッダの項目を追加する必要があります。
ASP.NET Web API 2 は、その項目の出力を、全ての API ・コントローラ毎・アクション毎に制御することができます。
また、2 つの通信パターン両方をサポート、またまた、Cookie の送信を制御するためのクレデンシャル等もサポートしています。
これらの制御を、属性で容易に設定することができる、これが、ASP.NET Web API 2 CORS サポートの本質になると思います。
ASP.NET Web API 2 の CORS サポート実装
パッケージは、NuGet 『Microsoft.AspNet.WebApi.Cors』で公開されています。
ASP.NET Web API 2 に依存しているので、1 では利用できません。
パッケージマネージャコンソールで、NuGetから取得するコマンドを打ちます。
Install-Package Microsoft.AspNet.WebApi.Cors
WebApiConfig.cs にて、CORS を有効にします。『config.EnableCors();』を追加します。
using System.Web.Http; namespace WebService { public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.EnableCors();// ココ config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); } } }
許可したいレベルにあわせて、EnableCors 属性を付与します。
↓コントローラ単位で設定する場合。
[EnableCors(origins: "http://site.com", headers: "*", methods: "*")] public class TestController : ApiController {....
全ての API や、アクション毎に設定する場合は、このセクションを参考にします。
origin は、Web API にアクセスしてくる元サイトのドメイン(最後のスラッシュはのぞきます)、
headers は、許可する HTTP リクエストのヘッダの項目、
methods は、許可する HTTP リクエストメソッドの項目を設定します。
"*" はなんでも許可する、という意味です。
ASP.NET 公式サイトの説明の最後にある「ICorsPolicyProvider」というのは、
[EnableCors]属性のカスタム属性を作成するためのインターフェイスです。
なんでもカスタムできる時代です。
以上!
どうして ASP.NET Web API 2 でないと利用できないのか、気になります・・・。
補足
Sending a CORS Request in IE
英語ですが、IE の CORS 対応状況についてまとめ。