読者です 読者をやめる 読者になる 読者になる

miso_soup3 Blog

主に ASP.NET 関連について書いています。

ASP.NET Web API 2 CORS サポートについて

ASP.NET Web API

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 つは、リクエストを送信する前に「こんなリクエスト送るね」と一度確認する方法です。

f:id:miso_soup3:20131008012945p:plain


f:id:miso_soup3:20131008021108p:plain
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 対応状況についてまとめ。