クロスドメイン制約 を JSONP で 回避 (ASP.NET MVC + jQuery)

0 件のコメント

クロスドメイン制約 を 回避 する サーバー実装 を ASP.NET MVC を用いて JSONP で実現します。

クロスドメイン通信 を実現するには "サーバー側" と "クライアント側" の2カ所に対して手を入れる必要があるかどうか考えます。 ここでは、"サーバー側" に手を加えて クロスドメイン通信 を実現する方法を載せます。 具体的には、JSONP形式 で レスポンス を返せるようにすることで、jQuery 等 で クロスドメイン通信 を行えるようにします。

今回は次の図に示すような環境でのクロスドメイン通信を想定し、 この状況でサーバーBにおいて JSONP 形式 で応答する 実装 を載せます。 個人的な趣味趣向の都合で ASP.NET MVC でサンプルコード を作成しています。

JSONP 形式 で 応答する サービス の実装

今回のサービスでは、JsonpHelper.csServiceController.cs を実装します。

  1. JSONP形式 の JavaScriptResult を返す ヘルパー関数 の作成

    JsonpHelper.cs

    namespace MvcApplication1.Helpers
    {
        using System;
        using System.Collections.Generic;
        using System.Linq;
        using System.Web;
        using System.Web.Mvc;
        using System.Web.Script.Serialization;
    
        public static class JsonpHelper
        {
            /// <summary>
            /// 指定されたオブジェクトをシリアル化し、 JSONP (JSON with padding) 形式にシリアル化する
            /// System.Web.Mvc.JavaScriptResult オブジェクトを作成します。
            /// </summary>
            /// <param name="controller">コントローラー</param>
            /// <param name="callback">コールバック関数名</param>
            /// <param name="data">シリアル化対象のオブジェクト</param>
            /// <returns>生成されたスクリプト</returns>
            public static JavaScriptResult Jsonp(this Controller controller, string callback, object data)
            {
                // シリアライザーのインスタンス生成
                var serializer = new JavaScriptSerializer();
    
                // ペイロード部分を生成
                var payload = serializer.Serialize(data);
    
                // JavaScriptResult を生成
                var javascriptResult = new JavaScriptResult()
                {
                    Script = string.Format("{0}({1});", callback, payload)
                };
    
                return javascriptResult;
            }
    
        }
    }
    
  2. サービス提供する コントローラー の 実装

    ServiceController.cs

    namespace MvcApplication1.Controllers
    {
        using System;
        using System.Collections.Generic;
        using System.Linq;
        using System.Web;
        using System.Web.Mvc;
        using Helpers;
    
        public class ServiceController : Controller
        {
            //
            // GET: /JsonpTest?callback=[callbackName]
    
            public ActionResult JsonpTest(string callback)
            {
                // クライアントへ返すデータ
                var data = new { name = "hoge" };
    
                // JSONP形式 のレスポンスを返却
                return this.Jsonp(callback, data);
            }
        }
    }
    

JSONP形式 で応答する サービス は使い回す可能性があると考えて、ヘルパー関数 にしました。 ヘルパー関数 (JsonpHelper.cs) 内では、JavaScriptSerializer を利用して オブジェクト から JSON への変換を行っています。 また、レスポンスは JavaScript なので、JavaScriptResult を生成、返却しています。

jQuery で jsonp リクエスト する クライアントスクリプト 実装

上記で実装した サービス に対して リクエスト する クライアント スクリプト の サンプルコード です。

$.ajax({
    url: 'http://serverb/MvcApplication1/Service/JsonpTest',
    crossDomain: true,
    dataType: 'jsonp'
    //jsonp: 'callback',             // コールバック関数 を指定する クエリパラメター の キー を指定
    //jsonpCallback: 'onjsonpload',  // コールバック関数 を指定する クエリパラメター の 値 を指定
}).done(function (data, textStatus, jqXHR) {
    $('#result').html(JSON.stringify(data));
}).fail(function (jqXHR, textStatus, errorThrown) {
    window.alert(textStatus);
});

上記で実装した サービス において コールバック関数 を指定する クエリパラメター が callback であるため、 サンプルコード では $.ajaxjsonp オプション および jsonpCallback オプション を利用していません。 クエリパラメター を変更する場合、$.ajaxjsonp オプション および jsonpCallback オプション をご参照ください。