.NET TIPS

[ASP.NET]Ajax.NETでAjaxプログラミングを効率化するには?

WINGSプロジェクト 土井 毅(監修:山田 祥寛)
2005/11/18

 Ajax.NETは、Michael Schwarz氏が自身のページで公開している.NET Framework用のAjaxフレームワークだ。

 別稿「枯れた新しいUI革命『Ajax』をASP.NETで活用する」でも示されたように、Ajax自体の仕組みは非常に単純なもので、何もこうしたフレームワークを利用しなくても実現できる。しかし、別稿でも指摘されていたように、標準的なASP.NETのみでAjaxを実装した場合、クライアント側では冗長なJavaScriptコードを記述していく必要がある。また、サーバ側でもHTTPリクエストを処理して引数をパースし、それを処理して結果をテキスト形式やXML形式で返すなど、それなりの対応が必要となる。

 Ajax.NETを使用すれば、クライアント側では通信部分の冗長なJavaScriptコードを除去し、あたかも直接サーバサイドのメソッドを呼び出しているかのように記述することができる。また、サーバ側でもHTTPを意識した処理が不要となり、通常の.NETクラスのメソッドにAjax.AjaxMethod属性を付加するだけでクライアントから呼び出すことが可能となる。

 次の図は、Ajax.NETによるクライアント/サーバ間通信の大まかな流れだ。

Ajax.NETの基本的な仕組み
Ajax.NETによるクライアント/サーバ間通信の大まかな流れを図示したもの。
  ページ上で発生した(クリックや何らかの変更などの)イベントをJavaScriptにより捕捉する。
  Ajax.NETのプロキシ・コード(後述)を使ってサーバ側のメソッドを呼び出す。この際、Ajax.NETは内部的にXmlHttpRequestオブジェクト(=HTTP通信用のオブジェクト)でサーバ側と通信を行う。
  サーバサイドは結果を.NETオブジェクト形式でクライアントに送信する。この際、Ajax.NETは内部で、.NETオブジェクトをJavaScriptで扱えるように型変換を行う。
  Dynamic HTML技術を使ってページの<必要な部分だけ>を動的に変更する。

 本稿では、このAjax.NETライブラリをASP.NETアプリケーションから利用する方法について紹介する。サンプル・プログラムは、別稿でも扱った郵便番号検索アプリケーションだ。以下はその実行例である。

Ajax.NETを利用した郵便番号による住所検索アプリケーション
画面左のテキストボックスに郵便番号を入力すると(上画面)、リアルタイムに右のテキストボックスに対応する住所をオート・コンプリートする(下画面)。ポストバックは行われないため、画面の更新は発生しない。

 本稿のサンプル・プログラムを動作させるには、あらかじめSQL Server/MSDE上のデータベースdotnetに以下のようなaddressテーブルを作成しておく必要がある。

フィールド名 データ型 概要
postnum VARCHAR(7) 郵便番号(主キー)
prefecture VARCHAR(10) 県名
city VARCHAR(50) 市町村名
other VARCHAR(50) 字、丁目、番地など
addressテーブルのフィールド・レイアウト
郵便番号情報については、日本郵政公社のサイトから提供されている郵便番号ダウンロードサービスを利用することで、CSV(カンマ区切りテキスト)形式のデータを入手できる。

 それではさっそく、具体的な構築手順を見ていくことにしよう。

1. Ajax.NETライブラリをインストールする

 Ajax.NETを利用するに当たっては、以下のサイトからファイルをダウンロードする必要がある。本稿では執筆時点での最新バージョンである5.7.22.2を例に取り上げる。

 Ajax.NETのインストールは簡単だ。上記のサイトからダウンロードしたファイルに含まれるAjax.dllをアプリケーションの仮想ディレクトリ直下のbinフォルダに配置するだけでよい。

2. web.configへ設定を追加する

 次に、Ajax.NETがJavaScriptのコードを自動生成するための設定をweb.configに追加する。

<configuration>
  <system.web>
    <httpHandlers>
      <add verb="POST,GET" path="ajax/*.ashx" type="Ajax.PageHandlerFactory, Ajax" />
    </httpHandlers>
   ……中略……
  <system.web>
</configuration>
Ajax.NETを利用するための設定(web.config)

 この設定によって、以下のJavaScriptを、それぞれ対応するURL呼び出しによって自動的に生成できるようになる。

URL 生成されるJavaScriptの内容
ajax/common.ashx Ajax.NETのプロキシ・コードが共通に使用するJavaScript関数群。主にXmlHttpRequest通信に関する定義が含まれる
ajax/{名前空間}.{クラス名},{アセンブリ名}.ashx サーバサイド・クラスのJavaScriptプロキシ。サーバサイドの指定されたメソッドについて、同名のJavaScriptメソッドが定義される。このプロキシ・コードが呼び出されると、サーバサイドとのXmlHttpRequest通信が行われ、サーバサイドのメソッドが呼び出される
Ajax.NETによって生成されるJavaScriptコード

3. サーバ側ロジックを準備する

 以下のような内容のPostNumberSearch.cs/PostNumberSearch.vbファイルを作成する。これらのファイルは、ASP.NETの「.aspx」ファイルではなく、通常の「.cs」「.vb」ファイルであることに注意していただきたい。

using System;
using System.Data;
using System.Data.SqlClient;

namespace Ajax.NET {
  public class PostNumberSearch {
    [Ajax.AjaxMethod]
    public string Search(string postnum){
      SqlConnection db = new SqlConnection("Data Source=(local);integrated security=SSPI;Persist Security Info=True;Initial Catalog=dotnet");
      try{
        // クエリ情報「postnum」の値をキーに
        // addressテーブルから住所情報を取得
        SqlCommand comm = new SqlCommand("SELECT prefecture,city,other FROM address WHERE postnum=@postnum", db);
        comm.Parameters.Add("@postnum", postnum);
        db.Open();
        SqlDataReader reader = comm.ExecuteReader();
        // レコードが取得できた場合、「県名+市町村名」で結果を出力
        if(reader.Read()){
          return reader.GetString(0) + reader.GetString(1) + reader.GetString(2);
        }else{
          return "存在せず";
        }
      }finally{
        db.Close();
      }
    }
  }
}
サーバ側ロジックのサンプル・プログラム(C#版:PostNumberSearch.cs)
 
Imports System
Imports System.Data
Imports System.Data.SqlClient

Namespace Ajax.NET
  Public Class PostNumberSearch
    <Ajax. AjaxMethodAttribute()> _
    Public Function Search(ByVal postnum As String) As String
      Dim db = New SqlConnection("Data Source=(local);integrated security=SSPI;Persist Security Info=True;Initial Catalog=dotnet")
      Try
        ' クエリ情報「postnum」の値をキーに
        ' addressテーブルから住所情報を取得
        Dim comm = New SqlCommand("SELECT prefecture,city,other FROM address WHERE postnum=@postnum", db)
        comm.Parameters.Add("@postnum", postnum)
        db.Open()
        Dim reader As SqlDataReader
        reader = comm.ExecuteReader()
        ' レコードが取得できた場合、「県名+市町村名」で結果を出力
        If reader.Read() Then
          Return reader.GetString(0) + reader.GetString(1) + reader.GetString(2)
        Else
          Return "存在せず"
        End If
      Finally
        db.Close()
      End Try
    End Function
  End Class
End Namespace
サーバ側ロジックのサンプル・プログラム(VB.NET:PostNumberSearch.vb)

 ここで実装しているSearchメソッドは、パラメータpostnumに与えられた郵便番号を基に、完全一致するレコードを検索し、都道府県名・市・そのほかの地名を連結して文字列型で戻り値を返す。

 このSearchメソッドの前にAjax.AjaxMethodAttributeという属性が指定されていることに注意していただきたい。この属性が指定されることにより、このメソッドがJavaScriptから呼び出されることを明示し、実行時には、このメソッドに対するプロキシ・コードが生成されることになる。

 以上のサンプル・プログラムのソース・ファイルは、使用に先立ってコマンド・プロンプトでコンパイルしておく必要がある。コンパイルの構文は以下のとおり。

csc /r:bin\ajax.dll /t:library /out:bin\ajax.NET.dll PostNumberSearch.cs
vbc /r:bin\ajax.dll /r:System.dll /r:System.Data.dll /t:library /out:bin\ajax.NET.dll PostNumberSearch.vb
サンプル・プログラムのコンパイル方法(上:C#、下:VB.NET)

4. Webフォームを作成する

 次に、いま作成したSearchメソッドを実行し、画面表示を行うためのWebフォームを作成する。

<%@ Page language="c#"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<html>
  <head><title>Ajax.Netによる郵便番号検索</title></head>
  <body>
  <h1>郵便番号による住所検索</h1>
  <form runat="server">
  <script language="JavaScript">
<!--
// テキストボックス「postnum」の内容が変更されたタイミングで実行
function search() {
  // サーバサイド・メソッド呼び出し
  PostNumberSearch.Search(
    document.getElementById("postnum").value, search_callback);
}
// コールバック関数
function search_callback(response) {
  if (response.error != null) { // 例外が送出された場合は
    alert(response.error); // ダイアログで表示
  } else {
    document.getElementById("address").value = response.value; // 結果を表示
  }
}
-->
  </script>
  郵便番号: <input type="text" name="postnum" size="10" maxlength="8" onchange="search()">
  <input type="text" name="address" size="40">
  </form>
  </body>
</html>
<script runat="server">
  void Page_Load(object sender, System.EventArgs e) {
    // 呼び出すメソッドを指定する
    Ajax.Utility.RegisterTypeForAjax(typeof(Ajax.NET.PostNumberSearch));
  }
</script>
Webフォームのサンプル・プログラム(C#:postnum_ajax_net_cs.aspx)
 
<%@ Page language="vb" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
  <head><title>Ajax.NETによる郵便番号検索</title></head>
  <body>
  <h1>郵便番号による住所検索</h1>
  <form runat="server">
  <script language="JavaScript">
<!--
// テキストボックス「postnum」の内容が変更されたタイミングで実行
function search() {
  // サーバサイド・メソッド呼び出し
  PostNumberSearch.Search(
    document.getElementById("postnum").value, search_callback);
}
// コールバック関数
function search_callback(response){
  if (response.error != null) { // 例外が送出された場合は
    alert(response.error); // ダイアログで表示
  } else {
    document.getElementById("address").value = response.value; // 結果を表示
  }
}
-->
  </script>
  郵便番号: <input type="text" name="postnum" size="10" maxlength="8" onchange="search()">
  <input type="text" name="address" size="40">
  </form>
  </body>
</html>
<script runat="server">
  Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    ' 呼び出すメソッドを指定する
    Ajax.Utility.RegisterTypeForAjax(GetType(Ajax.NET.PostNumberSearch))
  End Sub
</script>
Webフォームのサンプル・プログラム(VB.NET:postnum_ajax_net_vb.aspx)

 ここで注目していただきたいのは、以下の2点だ。

(1)Page_Loadメソッドで、Ajax.NETのJavaScriptコードを有効にする

 RegisterTypeForAjaxメソッドは、先ほど追加したPostNumberSearchクラスをクライアントサイドから呼び出すことを宣言するものだ。

Ajax.Utility.RegisterTypeForAjax(typeof(Ajax.NET.PostNumberSearch));
Ajax.Utility.RegisterTypeForAjax(GetType(Ajax.NET.PostNumberSearch))
RegisterTypeForAjaxメソッドの宣言方法(上:C#、下:VB.NET)

 実際には、このメソッドを記すことで、以下のようなJavaScriptコードのインクルード命令がHTML内に挿入される。それぞれのJavaScriptコードの役割については、手順2の表「Ajax.NETによって生成されるJavaScriptコード」を参照いただきたい。

<script type="text/javascript" src="/Ajax.NET/ajax/common.ashx"></script>
<script type="text/javascript" src="/Ajax.NET/ajax/Ajax.NET.PostNumberSearch,Ajax.NET.ashx"></script>
RegisterTypeForAjaxメソッドにより挿入されるJavaScriptコードのインクルード命令

(2)クライアント側で発生したイベントを捕捉する

 テキストボックス「postnum」が変更されたタイミング(=onchangeイベント発生時)では、JavaScriptのsearch関数を呼び出し、このsearch関数がサーバサイドで定義されたPostNumberSearch.Searchメソッドを呼び出す。

 ここで注目していただきたいのは、Ajaxで定番のXmlHttpRequest通信のコードがまったく存在しない点だ。パラメータは入力用テキストボックスに入力された文字列と、非同期呼び出し完了時のコールバック関数(search_callback)だけである。

 search_callback関数は、サーバサイドからの応答結果をパラメータ(ここではresponse)として受け取る。今回の場合は、C#やVB.NETで記述したSearchメソッドの戻り値がstring型として定義されているので、パラメータにより得られた結果値(response.value)をそのまま結果表示用のテキストボックスに表示しているというわけだ。

 ちなみに、サーバサイドで例外が発生した場合、response.errorのプロパティに以下のような例外に関する情報がセットされる。

  • response.error.nameプロパティ:例外の型名
  • response.error.descriptionプロパティ:例外のMessageプロパティ内容

 ここでは、response.errorがnullかどうかのチェックを行い、nullでない場合はJavaScriptのalert関数により例外の内容を表示している。response.errorのtoStringメソッドの出力結果では、nameプロパティとdescriptionプロパティの内容が連結される。

 例えばデータベースへの接続に失敗すると、以下のようなダイアログが表示されるはずだ。

データベース接続に失敗した場合のエラー・ダイアログの例
response.errorプロパティに含まれるnameプロパティとdescriptionプロパティの内容が連結されて表示される。これはサーバサイドで発生した例外の内容を示している。

 以上を理解したら、それぞれの.aspxファイルに実際にアクセスしてみよう。冒頭のような結果が得られれば成功だ。

 もしJavaScriptエラーが発生した場合は、以上の手順を再確認し、HTMLソースにJavaScriptプロキシ・コードのためのインクルード命令が正しく書き込まれているかどうかを確認していただきたい。End of Article

カテゴリ:Webフォーム 処理対象:Ajax
使用ライブラリ:AjaxMethod属性(Ajax名前空間)

この記事と関連性の高い別の.NET TIPS
[ASP.NET]Ajax.NETでデータセットやコレクションを操作するには?
[ASP.NET AJAX]Webサービス・ブリッジ機能により構造化データを受け渡しするには?(基本編)
[ASP.NET]ページを再読み込みせずにサーバと通信を行うには?
Visual Studioで静的HTMLページのJavaScriptコードをデバッグするには?
[ASP.NET AJAX]ローカリゼーション対応を行うには?(アセンブリ組み込み編)
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET TIPS」


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 記事ランキング

本日 月間