連載:Microsoft AJAX Library&JavaScriptプログラミング

最終回 MS AJAX Libのユーティリティ機能を活用しよう

山田 祥寛(http://www.wings.msn.to/
2008/05/30
Page1 Page2 Page3

MS AJAX Libは非ASP.NET環境でも利用可能

 いまさらではあるが、MS AJAX LibはASP.NET AJAXにおけるクライアントサイド・フレームワークである。確かにこれは正しい理解ではあるが、MS AJAX Libの性質を誤解しかねない理解でもある。というのも、MS AJAX LibはASP.NET AJAXの一部として――サーバサイド・フレームワークであるASP.NET AJAX Extensionsと連動して動作するだけではない。それ単体で、独立したJavaScriptライブラリとして動作することも可能なのである*2

*2 もちろん、Sys.Services名前空間やSys.WebForms名前空間など、サーバサイドとの連動を前提とした機能は、この限りではない。

 これまで述べてきたように、MS AJAX Libには強力なオブジェクト指向構文をはじめ、クロスブラウザ問題を吸収するためのブラウザ互換層など、JavaScriptプログラミングを効率化するためのさまざまな機能が用意されている。ASP.NET環境にとらわれず、(例えば)PHP(PHP:Hypertext Preprocessor)やJavaEE(Java Platform, Enterprise Edition)など、非ASP.NET/非Windows環境を利用している場合にも、1つの選択肢としてMS AJAX Libを検討してみてもよいのではないだろうか。

 ここでは、MS AJAX Libを非ASP.NET環境で利用する例として、PHP+MS AJAX Libでアプリケーションを作成してみよう。サンプル・アプリケーションは、「Yahoo!ウェブ検索Webサービス」を利用してサイト検索を行い、その結果をリスト表示するものだ(「Yahoo! ウェブ検索Webサービス」に関する詳細は、別稿「.NET TIPS:[ASP.NET]XmlDataSourceコントロールでYahoo!検索ウェブサービスを利用するには?」を参照)。



[検索]ボタンをクリック


図2 「Yahoo! ウェブ検索Webサービス」によるサイト検索の実行例
テキストボックスに入力されたキーワードで検索を行い、取得した結果をリスト形式で表示する。

 サンプル・アプリケーションの構成は、以下のとおりである。


図3 「Yahoo! ウェブ検索Webサービス」によるサイト検索の仕組み

 「Yahoo! ウェブ検索Webサービス」へのアクセスを行うのはPHPスクリプト(yahoo.php)の役割である。クライアント・ページ(yahoo.html)からは、このyahoo.phpに対してAjaxで非同期通信し、検索結果を取得するものとする*3

*3 PHPの動作に必要な環境の構築手順については、ここでは割愛する。詳細は筆者のサポートサイト「サーバサイド技術の学び舎 - WINGS」より「サーバサイド環境構築設定」を参照いただきたい。

それでは、以下に具体的な手順を紹介していく。

[1]MS AJAX Libのライブラリを配置する

 これまでASP.NET AJAXを利用するに当たって、読者がMS AJAX Libのインポートを意識することはなかったはずだ。というのも、ASP.NET環境では、ScriptManagerコントロールが必要なライブラリを自動的にアセンブリから取得し、ページにインポートしていたからだ。

 しかし、非ASP.NET環境では(当然)ScriptManagerコントロールは利用できないので、必要なライブラリ(「.js」ファイル)を公開フォルダに配置し、自分で明示的にインポートする必要がある。

 MS AJAX Libのソース・コードは、「AJAX : The Official Microsoft ASP.NET Site」からダウンロードが可能だ。ダウンロードしたMicrosoftAjaxLibrary.zipを解凍すると「MicrosoftAjaxLibrary」フォルダができるので、その配下の「System.Web.Extensions/3.5.0.0/3.5.21022.8」フォルダを「lib」とリネームしたうえで、フォルダごと公開フォルダ上の任意のサブフォルダに配置する(運用環境では「.debug.jsファイル」は不要なので、削除しても構わない)。

 ここでは、Apache HTTP Serverを利用していることを前提に、以下のようにファイルを配置するものとする。

/%APACHE_HOME%(Apacheのインストール・フォルダ)
    /htdocs
        /ajax
            yahoo.html(後述)
            yahoo.php(後述)
            /lib(MS AJAX Libのソース・コード)
Apache HTTP Server利用時に必要なファイルの配置

[2]「Yahoo! ウェブ検索Webサービス」にアクセスするためのPHPスクリプトを用意する

 次に、「Yahoo! ウェブ検索Webサービス」に検索キーワードを引き渡し、その結果をJSON(JavaScript Object Notation)形式で取得するための.phpファイルを作成する。

<?php
header('Content-Type: application/json;charset=UTF-8');

// 「Yahoo! ウェブ検索Webサービス」のアクセスに
// 必要なパラメータを定義

$opt = array(
  'appid'   => 'wings-project',
  'results' => 20,
  'query'   => $_GET['keywd']
);

// 配列$optからサービスへの問い合わせURLを生成

$url =
  'http://api.search.yahoo.co.jp/WebSearchService/V1/webSearch?'
                                              .http_build_query($opt);

// 問い合わせ結果をSimpleXMLElementオブジェクトに読み込み
$xml = simplexml_load_string(file_get_contents($url));

// SimpleXmlElementオブジェクト$xmlの内容をJSON形式に変換&出力
print(json_encode($xml));
リスト5 yahoo.php

[参考]末尾のデリミタは省略可能

 PHPの基本的な構文知識を持つ方ならば、リスト5で末尾のスクリプティング・デリミタ「〜?>」が省略されていることに違和感を覚えるかもしれない。しかし、これは間違いではない。PHPでは、スクリプト・ブロックの後方に、スクリプト以外のコンテンツが続かない限り、「〜?>」を省略することができる。

 むしろ「〜?>」の後方に不要な空白や改行を含めてしまった場合、これらはそのままクライアントに出力されてしまうため、場合によっては意図せぬレイアウトの乱れの原因となることもある。そのため、ファイル末尾のデリミタは省略するのが好ましい。

 PHPそのものの細かな構文については、本稿の守備範囲を超えるので割愛する。ここでは取りあえず、「与えられた検索キーワードに基づいて問い合わせURLを作成し、取得した結果をJSONデータとしてクライアントに応答している」とだけ理解しておけばよいだろう。このyahoo.phpを「〜/yahoo.php?keywd=ASP.NET」として呼び出した場合、以下のようなJSONデータが返されれば、スクリプトは正しく動作している。

{"@attributes":
  {"totalResultsAvailable":"278000",
   "totalResultsReturned":"20",
   "firstResultPosition":"1",
   "pgr":"251361"
  },
  "Result":[
    {"Title":"The Official Microsoft ASP.NET Site",
     "Summary":"Microsoft portal site for the ASP.NET development community..",
     "Url":"http:\/\/www.asp.net\/",
     "ClickUrl":"http:\/\/wrs.search.yahoo.co.jp\/l=WS1\...",
     "ModificationDate":"1209394800",
     "MimeType":"text\/html",
     "Cache":{
       "Url":"http:\/\/wrs.search.yahoo.co.jp\/……",
       "Size":"35293"
     }
    },

  ……後略……
リスト6 yahoo.phpの実行結果例(見やすいように適宜インデントや改行を加えている)

[3]クライアント側のコードを実装する

 次に、[2]で用意したPHPスクリプトに対して非同期通信要求を発行するための、クライアントサイドのコードを用意する。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Yahoo! ウェブ検索Webサービス</title>
<script type="text/javascript" src="./lib/MicrosoftAjax.js"></script>
<script type="text/javascript">
<!--

// [検索]ボタン・クリック時に実行されるイベント・ハンドラ
function search() {

  var req =  new Sys.Net.WebRequest();

  // 非同期通信先のURLをセット

  req.set_url(
    'yahoo.php?keywd=' + encodeURIComponent($get('keywd').value));

  // 非同期通信が完了した場合に実行する処理
  req.add_completed(

    function(exec, args) {

      // 応答データが正しく取得できた場合に、結果情報をリストに整形
      if (exec.get_responseAvailable()) {

        // 取得したJSONデータをデシリアライズ(オブジェクトに変換)
        var result = exec.get_object();

        // JSONデータから順に<Result>要素の内容を抽出
        // Title、Url、Summaryなどの情報を基に<dl>リストを整形

        var sb = new Sys.StringBuilder();
        sb.append('<dl>');

        for(var i = 0; i < result.Result.length; i++){
          sb.append('<dt><a target="_blank" href="');
          sb.append(result.Result[i].Url);
          sb.append('">');
          sb.append(result.Result[i].Title);
          sb.append('</a></dt><dd>');
          sb.append(result.Result[i].Summary);
          sb.append('</dd>');
        }
        sb.append('<dl>');

        // 生成した<dl>リストを<div id="result">に反映

        $get('result').innerHTML = sb.toString();

      } else {

        // 応答データが正しく取得できなかった場合、
        // エラー・ダイアログを表示
        if(exec.get_aborted() || exec.get_timedOut()){
          window.alert('予期せぬエラーが発生しました。');
        }
      }
    }
  );
  // 非同期通信を実行
  req.invoke();
}
//-->
</script>
</head>
<body>
<form name="fm">
キーワード:
<input type="text" name="keywd" size="15" />
<input type="button" value="検索" onclick="search()" />
<hr />
<div id="result"></div>
</form>
</body>
</html>
リスト7 yahoo.html

 サンプルの大まかな流れについては、リスト内のコメントを参考にしていただくとして、ここで注目していただきたいのは以下の3点である。

MS AJAX Libのコードをインポートする

 前述のとおり、非ASP.NET環境では必要なライブラリを明示的にインポートしておく必要がある。MS AJAX Libの最低限の機能を利用するために必要なファイルは「MicrosoftAjax.js」だけである。MicrosoftAjaxWebForms.jsの方は、UpdatePanelコントロールとの連動を前提としたSys.WebForms名前空間の機能を提供するものなので、非ASP.NET環境では通常利用する機会はないはずだ。

非同期通信を管理するのはSys.Net.WebRequestオブジェクトの役割

 Sys.Net.WebRequestオブジェクトは、AJAX通信の標準的なオブジェクトであるXMLHttpRequestオブジェクトのごく薄いラッパーともいうべきオブジェクトだ。別稿「枯れた新しいUI革命「Ajax」をASP.NETで活用する」でも紹介したように、XMLHttpRequestオブジェクトの実装はブラウザやそのバージョンによって異なる。このため、XMLHttpRequestオブジェクトを直接に使ってAjax機能を実装する場合、XMLHttpRequestオブジェクト1つを生成するにもクロスブラウザを意識した冗長なコードを記述する必要がある。

 しかし、Sys.Net.WebRequestオブジェクトを利用することで、クロスブラウザを意識することなく、かつ、XMLHttpRequestオブジェクトを利用するよりもシンプルに同等のコードを記述することが可能となる。

 Sys.Net.WebRequestオブジェクトで利用可能なメンバは、以下のとおりだ。

メンバ 概要
[E]completed 非同期通信が完了したタイミングで発生
[M]getResolvedUrl() 問い合わせURLを取得
[M]invoke() 非同期通信を実行
[P]body 要求本体を取得/設定
[P]executor エグゼキュータ(後述)を取得/設定
[P]header リクエスト・ヘッダを取得(読み取り専用)
[P]httpVerb HTTPメソッド(GET|POST)を取得/設定
[P]timeout 通信タイムアウト時間(ミリ秒)を取得/設定
[P]url 問い合わせURLを取得/設定
[P]userContext ユーザー・コンテキストを取得/設定
表3 Sys.Net.WebRequestオブジェクトで利用可能なメンバ
[P][M][E]は、プロパティ、メソッド、イベントを意味する。

 なお、プロパティ値にアクセスするには、以下の形式で記述する。

・オブジェクト名.get_プロパティ名()
・オブジェクト名.set_プロパティ名(設定値)

 また、イベント・ハンドラを設定/削除するには、以下の形式で記述する。

・オブジェクト名.add_イベント名(ハンドラ)
・オブジェクト名.remove_プロパティ名(ハンドラ)

 非同期通信を行うために最低限必要な設定は、urlプロパティとcompletedイベントである。ここでは、テキストボックスに入力された値を基に問い合わせURLを組み立て、completedイベント・ハンドラでサーバからの応答をリスト形式に整形しているというわけだ。Sys.Net.WebRequestオブジェクトの設定に基づいて非同期通信要求を開始するのは、invokeメソッドの役割である。

サーバからの応答を取得するのはSys.Net.XMLHttpExecutorオブジェクトの役割

 completedイベント・ハンドラに注目してみよう。completedイベント・ハンドラは第1引数として、Sys.Net.XMLHttpExecutorオブジェクト(エグゼキュータ)を受け取る。このオブジェクトは非同期通信要求を操作、関連する情報を管理するためのオブジェクトだ。Sys.Net.XMLHttpExecutorオブジェクトの主なメンバは、以下のとおり。

メンバ 概要
[M]abort() 実行中の非同期通信要求を中断
[M]executeRequest() 非同期通信を開始
[M]getAllResponseHeaders() すべての応答ヘッダを取得
[M]getResponseHeader(name) 指定された応答ヘッダを取得
[P]aborted 要求が中止されたか
[P]object 応答データ(JSONから評価されるオブジェクト)を取得
[P]responseAvailable 要求が正常に終了したか
[P]responseData 応答データ(テキスト形式)を取得
[P]started 非同期通信を開始したか
[P]statusCode 応答ステータス・コードを取得
[P]statusText 応答ステータス・メッセージを取得
[P]timedOut 要求がタイムアウトしたか
[P]xml 応答データ(XMLDOMオブジェクト)を取得
[P]webRequest 関連付いたWebRequestオブジェクトを取得
表4 Sys.Net.XMLHttpExecutorオブジェクトの主なメンバ
[P][M]は、プロパティ、メソッドを意味する。

 completedイベントは、あくまで通信が完了したことを示すイベントであるにすぎない。従って、通信の状態はresponseAvailable/aborted/timedOutプロパティで確認してから処理を行う必要がある。リスト7では、要求が正常に終了した場合のみ応答データを取得し、これをリストに整形している。応答データを取得するには、object/responseData/xmlプロパティのいずれかを利用できる。今回のように応答データがJSON形式で返されることが分かっている場合には、objectプロパティを利用することで、JavaScriptオブジェクトとして評価済みの状態で応答を取得することが可能だ。

 以上を理解したら、さっそく作成したサンプル・プログラムを実行してみよう。冒頭の画面(図2)のように、任意のキーワードで検索を実行すると、これに対応する検索結果がページ下部にリスト表示されることが確認できれば成功だ。

 以上、本連載ではASP.NET AJAXのクライアントサイド・フレームワークであるMS AJAX Libについて解説してきた。ASP.NET AJAXというと、とかくサーバサイド・フレームワークであるASP.NET AJAX Extensionsに目が行きがちかもしれないが、アプリケーション固有の要件を実現するには、JavaScriptによるコーディングと、これを支援するMS AJAX Libの理解は欠かせない。

 サーバサイドでの開発に慣れた読者諸氏からしてみると、JavaScriptによるコーディングにはなかなか抵抗があるかもしれないが、この2月に登場した統合開発環境Visual Studio 2008ではJavaScriptサポートも大幅に強化され、従来に比べればJavaScriptプログラミングも随分と効率化されている(「特集:ASP.NETアプリ開発者のためのVisual Studio 2008新機能」を参照)。もしもこれまでJavaScriptプログラミングを敬遠してきた方がいるならば、これを機会に、ぜひともJavaScriptに再入門し、.NET環境標準のJavaScriptライブラリであるMS AJAX Libにも目を向けてみてはどうだろうか。本連載と、その姉妹連載である「連載:Ajax時代のJavaScriptプログラミング再入門」が、その手掛かりとなることを願う。


 INDEX
  Microsoft AJAX Library&JavaScriptプログラミング
  最終回 MS AJAX Libのユーティリティ機能を活用しよう
    1.文字列連結を効率的に行うには?/オブジェクトの内容を確認するには?
  2.MS AJAX Libは非ASP.NET環境でも利用可能
    3.[コラム]PHP for Microsoft AJAX Library
 
インデックス・ページヘ  「Microsoft AJAX Library&JavaScriptプログラミング」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間