ASP.NET MVC で CORS

現在の ASP.NET テクノロジで JSON Web サービスを構築する場合、
RESTful な API にするには ASP.NET Web API を、
RPC スタイルの API にするには ASP.NET MVC を利用することと思います。

また、JSON Web サービスへのクロスドメインでのアクセスを許可するには、
Cross-Origin Resource Sharing (CORS) または JSONP をサポートする必要があります。

CORS をサポートするためのライブラリは、

として提供されています。
しかし、ASP.NET Web API ではこれを利用できるのですが、ASP.NET MVC では利用する方法がないようです。

そこで以下では、ASP.NET MVC で CORS を自前でサポートする方法について考えます。

 

まず、ASP.NET MVC で JSON Web サービスを実装するには、次の例のようにコントローラーを作成します。
GET と POST でサービスを実装します。


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace CorsMvc.Controllers
{
    public class JsonController : Controller
    {
        // GET /json/uuid
        public ActionResult Uuid()
        {
            var data = Guid.NewGuid();
            return Json(data);
        }

        // POST /json/uuid
        [HttpPost]
        public ActionResult Uuid(int count)
        {
            var data = Enumerable.Repeat(false, count).Select(_ => Guid.NewGuid()).ToArray();
            return Json(data);
        }

        new ActionResult Json(object data)
        {
            Response.Headers["Expires"] = "-1";

            return Json(data, JsonRequestBehavior.AllowGet);
        }
    }
}


 

この Web サービスをブラウザーで確認するには、次のような HTML を作成します。
まずは同一ドメインの場合です。


<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>JSON Test</title>
    <script src="//ajax.aspnetcdn.com/ajax/jQuery/jquery-2.1.0.min.js" type="text/javascript"></script>
</head>
<body>
    <div>
        <h1>JSON Test</h1>
        <h3>GET /json/uuid</h3>
        <button id="GetUuidButton">Generate</button>
        <pre id="GetUuidResult"> </pre>
        <h3>POST /json/uuid</h3>
        <button id="PostUuidButton">Generate</button>
        <pre id="PostUuidResult"> </pre>
    </div>
    <script type="text/javascript">
        $(function () {
            $("#GetUuidButton").click(function () {
                $.getJSON("/json/uuid").done(function (data) {
                    $("#GetUuidResult").text(data);
                });
            });
            $("#PostUuidButton").click(function () {
                $.post("/json/uuid", { count: 3 }).done(function (data) {
                    $("#PostUuidResult").text(data);
                });
            });
        });
    </script>
</body>
</html>


 

これで、Web サービスの動作を確認できます。

同一ドメインでのアクセス

 

次に、Web サービスの呼び出し先の URL を次のように変更して、異なるドメインに HTML を配置して実行します。


    <script type="text/javascript">
        $(function () {
            $("#GetUuidButton").click(function () {
                $.getJSON("http://localhost:58201/json/uuid").done(function (data) {
                    $("#GetUuidResult").text(data);
                });
            });
            $("#PostUuidButton").click(function () {
                $.post("http://localhost:58201/json/uuid", { count: 3 }).done(function (data) {
                    $("#PostUuidResult").text(data);
                });
            });
        });
    </script>


 

すると、Web サービスの呼び出しに失敗します。
実際には通信は発生しているのですが、ブラウザーにより不可と判断されます。

CORS でクロスドメインでのアクセスを許可するには、
HTTP 応答の Access-Control-Allow-Origin ヘッダーにアクセスを許可するドメインを指定する必要があり、
ASP.NET MVC の場合は次のように自前でこの処理を実装します。
最初にコントローラーの中で作成した Json メソッドに 1 行追加するだけです。


new ActionResult Json(object data)
{
    Response.Headers["Expires"] = "-1";
    Response.Headers["Access-Control-Allow-Origin"] = "*";

    return Json(data, JsonRequestBehavior.AllowGet);
}


 

これで、クロスドメインで Web サービスにアクセスできるようになりました。

クロスドメインでのアクセス

 

GET の場合も POST の場合も、プレフライト要求が発生する条件に当てはまらないようなシンプルな要求の場合、
Access-Control-Allow-Origin ヘッダーのみで対応ができます。
また、プレフライト要求が発生する場合も、
今回のように必要なヘッダーを HTTP 応答に追加することで実現できると思います。

 

また、次のように Web.config でカスタム ヘッダーを設定する方法もあります。
この場合、すべての HTTP 応答に対してカスタム ヘッダーが追加されることになります。


<configuration>
  <system.webServer>
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
      </customHeaders>
    </httpProtocol>
  </system.webServer>
</configuration>


 

次回に続きます。
ASP.NET MVC で JSONP

バージョン情報
ASP.NET MVC 5.1.2

参照
HTTP access control (CORS)
CORS(Cross-Origin Resource Sharing)について整理してみた
ASP.NET Web API 2 における CORS サポート
Windows Azure ストレージ: CORS の導入
ASP.NET Web API 2 CORS サポートについて
カスタム ヘッダー <customHeaders> (TechNet)
HTTP Protocol Settings <httpProtocol>

カテゴリー: .NET Framework. タグ: . 1 Comment »

コメント / トラックバック1件 to “ASP.NET MVC で CORS”

  1. ASP.NET MVC で JSONP | Do Design Space Says:

    […] ASP.NET MVC で CORS では、 JSON Web サービスへのクロスドメインでのアクセスを CORS […]


コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

%d人のブロガーが「いいね」をつけました。