WebSurfer's Home

トップ > Blog 1   |   ログイン
APMLフィルター

jQuery.ajax で JSONP

by WebSurfer 2017年5月3日 14:30

jQuery.ajax を使うと、JSONP(JSON with Padding・・・script タグを使用してクロスドメインでデータを取得する仕組み)を利用してデータを取得するのがかなり簡単にできるという話を書きます。

JSONP の応答を alert に表示

何が簡単になるかというと以下のことを jQuery.ajax が自動的にやってくれることです。

  1. jQuery.ajax を呼び出した時点で script タグを生成し DOM ツリーへ追加。(本来は、src 属性に呼出先の URL を設定した script タグを生成して DOM ツリーに追加するためのスクリプトを自力で書かなければなりません)
  2. 呼出先の URL にコールバックの名前を指定するクエリ文字列 &callback=jQuery... を追加。
  3. 応答が返ってくるとコールバックが呼び出され、引数に設定された JSON 文字列が JavaScript オブジェクトにパースされ、success: function (data) の data に渡される。

以下に具体例を書きます。MVC を例にとっていますが、もちろん Web Forms でも同様なことは可能です。

まず、ブラウザからの要求を受けて応答を返す窓口を作ります。MVC アプリの場合は、以下のようにアクションメソッドを使うのが簡単そうです。

具体的にどういう操作をしているかはコメントに書きましたのでそちらを見てください。

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using AdventureWorksLT;
using System.Web.Script.Serialization;

namespace Mvc5App.Controllers
{
  public class AddressesController : Controller
  {
    // サンプルデータベース AdventureWorksLT をベースに
    // Visual Studio のウィザードで作った EDM を利用。
    // AdventureWorksLTEntities は DbContext を継承
    private AdventureWorksLTEntities db = 
                            new AdventureWorksLTEntities();

    // JSONP が呼び出すアクションメソッド
    public ActionResult Jsonp(int? id, string callback)
    {
      if (id == null)
      {
          return new HttpStatusCodeResult(
                                 HttpStatusCode.BadRequest);
      }

      // Address テーブルから指定された AddressID(主キー)
      // でレコードを検索。
      // 当該レコードの AddressID, AddressLine1, City フィー
      // ルドのデータを匿名クラスのオブジェクトとして取得
      var address = (from a in db.Address
         where a.AddressID == id
         select new { a.AddressID, a.AddressLine1, a.City }).
         FirstOrDefault();

      if (address == null)
      {
          return HttpNotFound();
      }

      // 取得したオブジェクトを JSON 文字列にシリアライズし
      // 変数 callback に名前が指定されたコールバックメソッ
      // ドの引数に設定。
      // code は「コールバック(JSON 文字列)」という文字列に
      // なる
      JavaScriptSerializer ser = new JavaScriptSerializer();
      string code = string.Format("{0}({1})", 
                          callback, ser.Serialize(address));

      // 文字列「コールバック(JSON 文字列)」を返す。その際
      // ヘッダに Content-Type: application/x-javascript; が
      // 付与される
      return JavaScript(code);
    }
    // ・・・中略・・・
  }
}

上記のアクションメソッドを、例えば /Addresses/Jsonp?id=25&callback=name で呼び出すと、以下の応答が返ってきます。

name({"AddressID":25,"AddressLine1":"9178 Jumping St.","City":"Dallas"})

呼び出し側(View)のコードは以下のようになります。上にも書きましたが、script 要素を DOM に追加するコードを書く必要はありません。以下のコードだけで jQuery.ajax が自動的にやってくれます。

<input type="text" id="tb1" />
<input type="button" value="検索" onclick="btn_click()" />

@section Scripts {
  <script type="text/javascript">
  //<![CDATA[
    function btn_click() {
      var address = '/Addresses/Jsonp?id=' + $("#tb1").val();

      $.ajax({
          url: address,
          dataType: 'jsonp',
          success: function (data) {
              alert(data.AddressID + ', ' +
                    data.AddressLine1 + ', ' + 
                    data.City);
          }
      });
    }
  //]]>
  </script>    
}

上記には jQuery の外部スクリプトファイルの参照が書いてありませんが、Visual Studio 2015 のテンプレートで自動生成した _Layout.cshtml を利用していますので、デフォルトで取り込まれるようになっています。

_Layout.cshtml を利用していますので、インラインのスクリプトは、上記のように View に @section Scripts { ... } を追加して、その中に書くのが適当です。header タグ内に書くと jQuery の外部スクリプトファイルが取り込まれる前になってしまいますので注意してください。

コールバックのメソッド名は、上にも書きましたが、jQuery.ajax がクエリ文字列として自動的に自動的にデフォルトの名前を追加しますので、それを利用しています。(デフォルトの名前では不都合がある場合は指定することも可能です)

data には、コールバックの引数の JSON 文字列が JavaScript オブジェクトに変換されて渡されます。なので、上記のようにプロパティを使ってデータを取得することができます。

Tags: ,

AJAX

IIS Express と gzip 圧縮

by WebSurfer 2017年4月24日 23:38

Visual Studio で ASP.NET Web アプリを開発する際に使用される IIS Express はデフォルトで gzip 圧縮された応答を返すという話を書きます。

(Visual Studio 2015 Community Update 3 と一緒にデフォルトでインストールされる IIS 10.0 Express の話です。他のバージョンは不明です)

Fiddler によるキャプチャ結果

Visual Studio 2010ではデフォルトで ASP.NET 開発サーバーを使用します。IIS Express も、先の記事「IIS Express をインストールしました」に書きましたように、別途ダウンロードしてインストールすれば使用可能です。

しかしながら、Visual Studio 2015 では ASP.NET 開発サーバーを使用できませんので、IIS Express またはローカル IIS のいずれかを使うことになります。

当然ながらローカル IIS より IIS Express の方が手軽かつ便利ですし、以下の理由もあって、少なくとも開発の初期には IIS Express を使わざるを得ません。

  1. EF Code First + LocalDB の機能を使ってユーザー情報のストア(.mdf ファイル)を App_Data フォルダに生成するというところがローカル IIS ではできません。
  2. LocalDB を動かすにはユーザープロファイルが必要なので IIS Express を使わざるを得ません。(ローカル IIS は Windows Service として動くのでユーザープロファイルを持たない)

ローカル IIS を使うには、IIS 上でのアプリケーションの設定とフォルダの権限の設定はもちろん、EF Code First + LocalDB の機能で App_Data フォルダに生成された .mdf ファイルをコピーして SQL Server にアタッチし、Web アプリから SQL Server に接続できるようにするという設定の変更が必要になります。

ということで、Visual Studio 2015 を使っての ASP.NET Web アプリの開発には、自分もやむを得ず(?)ほとんど使ったことがない IIS Express を使い始めました。

ところが IIS Express とローカル IIS ではデフォルトの設定が違っているようで、まず気が付いたのが gzip 圧縮です。

IIS で静的コンテンツの圧縮をかけるにには、MSDN Blog の記事「IIS7 以降の静的コンテンツの圧縮について」によると、役割サービスで [静的コンテンツの圧縮] を有効にするなどの設定が必要とのことです。

ローカル IIS にはそのような設定はしてないので gzip 圧縮はかかりません。ところが、IIS Express ではデフォルトで gzip 圧縮がかかります。上の画像を見てください。

IIS Express の ApplicationHost.config を調べてみると以下の設定がありました。これの、<dynamicTypes> から </staticTypes> までをコメントアウトすると gzip 圧縮はかからなくなります。

<httpCompression 
  directory="%TEMP%\iisexpress\IIS Temporary Compressed Files">
  <scheme name="gzip" dll="%IIS_BIN%\gzip.dll" />
  <dynamicTypes>
    <add mimeType="text/*" enabled="true" />
    <add mimeType="message/*" enabled="true" />
    <add mimeType="application/javascript" enabled="true" />
    <add mimeType="application/atom+xml" enabled="true" />
    <add mimeType="application/xaml+xml" enabled="true" />
    <add mimeType="*/*" enabled="false" />
  </dynamicTypes>
  <staticTypes>
    <add mimeType="text/*" enabled="true" />
    <add mimeType="message/*" enabled="true" />
    <add mimeType="image/svg+xml" enabled="true" />
    <add mimeType="application/javascript" enabled="true" />
    <add mimeType="application/atom+xml" enabled="true" />
    <add mimeType="application/xaml+xml" enabled="true" />
    <add mimeType="*/*" enabled="false" />
  </staticTypes>
</httpCompression>

まだ調べてませんけど、gzip 圧縮以外にも違うところがありそうです。重大な違いに気が付いたら別途記事を書くつもりです。

Tags: ,

DevelopmentTools

ApplicationHost.config の場所

by WebSurfer 2017年4月23日 13:47

Visual Studio で ASP.NET Web アプリを開発するときに利用できる IIS Express 用の ApplicationHost.config ファイルはどこにあるかという話を書きます。

(注:Windows 10 64-bit に Visual Studio 2015 Community Update 3 をインストールするときに一緒にインストールされた IIS 10.0 Express の話です)

ちなみに、IIS 用の ApplicationHost.config ファイルは、TexhNet の記事「ApplicationHost.configの紹介」に書いてある通り、system32¥inetsrv¥config フォルダにあります。

IIS Express は IIS 用の ApplicationHost.config ファイルを共有しません。別の場所に別の ApplicationHost.config ファイルが存在し、それを使用します。

自分の PC には Visual Studio 2010 Professional SP1 と Visual Studio 2015 Community Update 3 がインストールされており、それらから Web アプリを IIS Express 上で実行する場合、使用される ApplicationHost.config ファイルは以下の通りとなります。

(注:他のバージョンの Visual Studio, IIS Express の場合は不明です。また、以下はデフォルトの場合で、設定によっては変更できるかもしれません・・・が、未確認です)

(1) VS2010

OneDrive の Documents\IISExpress\config フォルダ内の ApplicationHost.config ファイル。(OneDrive を使わない場合は C:\Users\ユーザー名\Documents\IISExpress\config フォルダ)

ApplicationHost.config

(2) VS2015

各ソリューションのフォルダ内の ApplicationHost.config ファイル。下の画像の例を見てください。Mvc5App がソリューションのフォルダで、各ソリューションごとに別のファイルが使用されます。

ApplicationHost.config

MSDN Blog の記事「IIS Expressの仮想ディレクトリを applicationhost.config から削除する方法」によると、上記 (1) の Documents フォルダ下の ApplicationHost.config ファイルが、全 Web アプリで共用されるようなことが書かれていますが、これは少なくとも自分の PC にインストールしてある VS2015 には当てはまらないようです。

実は、そのことを知らなくて、上記 (1) の ApplicationHost.config ファイルの設定をどのように変えても、VS2015 から IIS Express で起動する Web アプリに設定変更が反映されないのに、2 時間ほど悩んだのは内緒です。(笑)

Tags:

DevelopmentTools

About this blog

2010年5月にこのブログを立ち上げました。その後 ブログ2 を追加し、ここは ASP.NET 関係のトピックス、ブログ2はそれ以外のトピックスに分けました。

Calendar

<<  2017年9月  >>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

View posts in large calendar