特集

枯れた新しいUI革命「Ajax」をASP.NETで活用する

山田 祥寛(http://www.wings.msn.to/
2005/08/24

Page1 Page2 Page3 Page4

Ajax+ASP.NETによる郵便番号あいまい検索(XML通信)

 さて、お次のサンプルは、郵便番号をキーにしたあいまい検索の例だ。これは、サーバからの応答としてXML(eXtensible Markup Language)形式を利用した例ともなる。

 前節の例では、サーバから返されるデータが単純な文字列であったので、比較的コードもシンプルであったが、Ajaxアプリケーションでやりとりするのは、このような単純な文字列ばかりではない。このサンプルのように、郵便番号や住所のような複合的な情報を(しかも複数件)持つような複雑なデータを受け渡したいというケースも多い。

 そのような場合には、応答データをXML形式に整形して送信するとよいだろう。すでにさまざまな記事でも紹介されているように、XMLはプラットフォームを問わないニュートラルなデータ形式だ。XMLを利用することで、階層を持った構造データをクライアント/サーバ間で簡単にやりとりすることができる。

 次の画面は、ここで作成するサンプルの実行画面である。3桁以上の郵便番号を入力すると、前方一致した住所情報(上位15件)がフォーム下部にリスト表示される。リスト表示された住所をクリックすると、その内容がフォームに反映されるというわけだ。住所検索はAjaxによる非同期通信で行っているため、ページ自体の遷移は発生しない。

Ajaxを利用した住所検索アプリケーション(あいまい検索対応)
左のテキストボックスに3桁以上の郵便番号を入力すると、フォーム下部に該当する住所情報の上位15件をリスト表示する。リスト表示された住所情報をクリックすると、その内容をフォームに反映することができる。

 それでは具体的なコードを見ていくことにしよう。

■サーバ側でのあいまい検索の実装

 サーバ側では、クライアントから送信された郵便番号をキーに、先ほど作成したaddressテーブルに対して検索処理を行う。検索結果はRepeaterコントロールでXML形式のデータに整形し、クライアントに送信するものとする。

<?xml version="1.0" encoding="UTF-8" ?>
<%@ Page ContentType="text/xml" Language="C#" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>

<script runat="Server">
void Page_Load(Object sender, EventArgs e) {

  SqlConnection db = new SqlConnection("Data Source=(local);User ID=sa;Password=sa;Persist Security Info=True;Initial Catalog=dotnet");

  // クエリ情報"postnum"をキーにaddressテーブルをあいまい検索、
  // 上位15件の情報を取得
  SqlCommand comm = new SqlCommand("SELECT TOP 15 postnum,prefecture,city,other FROM address WHERE postnum LIKE @postnum ORDER BY postnum", db);
  comm.Parameters.Add("@postnum", Request.QueryString["postnum"] + "%");
  db.Open();
  SqlDataReader reader = comm.ExecuteReader();

  // 取得したDataReaderをRepeaterコントロールにバインド
  data.DataSource=reader;
  data.DataBind();
  db.Close();
}
</script>

<asp:Repeater id="data" runat="Server">
  <HeaderTemplate>
    <Result>
  </HeaderTemplate>
  <ItemTemplate>
    <Data>
      <PostNum>
        <%# DataBinder.Eval(Container.DataItem, "postnum") %>
      </PostNum>
      <Address>
        <%# DataBinder.Eval(Container.DataItem, "prefecture") %>
        <%# DataBinder.Eval(Container.DataItem, "city") %>
        <%# DataBinder.Eval(Container.DataItem, "other") %>
      </Address>
    </Data>
  </ItemTemplate>
  <FooterTemplate>
    </Result>
  </FooterTemplate>
</asp:Repeater>
addressテーブルに対するあいまい検索の結果をXML形式で出力するWebフォーム(C#版:postnum_like_server_cs.aspx)
 
<?xml version="1.0" encoding="UTF-8" ?>
<%@ Page ContentType="text/xml" Language="VB" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>

<script runat="Server">
Sub Page_Load(sender As Object, e As EventArgs)

  Dim db As New SqlConnection("Data Source=(local);User ID=sa;Password=sa;Persist Security Info=True;Initial Catalog=dotnet")

  ' クエリ情報"postnum"をキーにaddressテーブルをあいまい検索、
  ' 上位15件の情報を取得
  Dim comm = New SqlCommand("SELECT TOP 15 postnum,prefecture,city,other FROM address WHERE postnum LIKE @postnum ORDER BY postnum", db)
  comm.Parameters.Add("@postnum",Request.QueryString("postnum") & "%")
  db.Open()
  Dim reader As SqlDataReader = comm.ExecuteReader()

  ' 取得したDataReaderをRepeaterコントロールにバインド
  data.DataSource = reader
  data.DataBind()
  db.Close()
End Sub
</script>

<asp:Repeater id="data" runat="Server">
  <HeaderTemplate>
    <Result>
  </HeaderTemplate>
  <ItemTemplate>
    <Data>
      <PostNum>
        <%# DataBinder.Eval(Container.DataItem, "postnum") %>
      </PostNum>
      <Address>
        <%# DataBinder.Eval(Container.DataItem, "prefecture") %>
        <%# DataBinder.Eval(Container.DataItem, "city") %>
        <%# DataBinder.Eval(Container.DataItem, "other") %>
      </Address>
    </Data>
  </ItemTemplate>
  <FooterTemplate>
    </Result>
  </FooterTemplate>
</asp:Repeater>
addressテーブルに対するあいまい検索の結果をXML形式で出力するWebフォーム(VB.NET版:postnum_like_server_vb.aspx)

 ロジックとしては完全一致が前方一致になった以外は前項と同様なので、殊更に特筆すべき点はない。検索に使用するSQL文では、「TOP 15」により上位15件を、WHERE句のLIKE文によりあいまい検索を行っている。

  ここでは(例えば)、

http://localhost/netIns/ajax/postnum_like_server_cs.aspx?postnum=421041

のようなパラメータを付加したURLでWebフォームにアクセスし、以下のようなXMLデータが返されることを確認してほしい。

<?xml version="1.0" encoding="UTF-8" ?>
<Result>
  <Data>
    <PostNum>4210411</PostNum>
    <Address>静岡県榛原郡榛原町坂口</Address>
  </Data>
  <Data>
    <PostNum>4210412</PostNum>
    <Address>静岡県榛原郡榛原町坂部</Address>
  </Data>
  ……中略……
</Result>
上記のWebフォームにブラウザでアクセスした場合に返されるXMLデータの例

■クライアント・ページでXML文書を処理する

 ここで注目していただきたいのは、次に示すクライアント・ページの実装だ。

<%@ Page ContentType="text/html" Language="VB" %>
<html>
<head>
<title>Ajaxによる郵便番号検索</title>

<script language="JavaScript">
<!--
// テキストボックス"postnum"内でキー入力されたタイミングで実行
function search(){
  try {
    xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
  } catch(e) {
    xmlHttp=new XMLHttpRequest();
  }

  // XMLHttpRequestオブジェクトの状態が変更されたタイミング
  // で行うべき処理を定義
  xmlHttp.onreadystatechange=function() {

    // データ受信に成功した場合、受信データから郵便番号、
    // 住所情報を取り出し、HTMLに整形したうえで、
    // <div>タグ上にコンテンツを反映
    if (xmlHttp.readyState == 4) {
      if (xmlHttp.status == 200) {
        var aData = xmlHttp.responseXML.documentElement;
        var data = aData.childNodes;
        contents = "<ol type='square'>";
        for (i =0; i < data.length; i++) {
          contents += "<li><a href='JavaScript: void(0)' onclick=\"document.fm.postnum.value="
          + data[i].childNodes[0].firstChild.nodeValue
          + ";document.fm.address.value='"
          + data[i].childNodes[1].firstChild.nodeValue
          + "';\">"
          + data[i].childNodes[0].firstChild.nodeValue
          + "&nbsp;"
          + data[i].childNodes[1].firstChild.nodeValue
          + "</a></li>";
        }
        contents+="</ol>";
        result.innerHTML=contents;
      }
    }
  }

  // 入力文字が3桁以上の場合に、HTTP GETメソッドで
  // postnum_like_server_cs.aspxにデータを送信
  if (document.fm.postnum.value.length >= 3) {
    xmlHttp.open("GET",
      "postnum_like_server_cs.aspx?postnum="
      + document.fm.postnum.value.replace("-", ""),true);
    xmlHttp.send(null);
  }
}
-->
</script>
</head>
<body>
<h1>郵便番号による住所検索</h1>
<form name="fm">
  郵便番号:
  <input type="text" name="postnum" size="10" maxlength="8"
    onkeyup="search()" />
  <input type="text" name="address" size="40" />
  <div id="result" />
</form>
</body>
</html>
postnum_like_server_cs.aspx(postnum_like_server_vb.aspx)から取得した住所情報を反映するWebフォーム(postnum_like_client1.aspx)

 本節で注目していただきたいのは、コード中、太字で記載している部分だ。サーバから応答されたXMLデータをJavaScriptで取得するには、XMLHttpRequestオブジェクトのresponseXMLプロパティを利用する。

 取得したXMLデータはXMLDocumentオブジェクトとして返されるので、後は一般的なDOMによって必要なデータを取り出せばよい。DOMに関しては膨大な仕様でもあるのでここでは割愛するが、詳細はMSDN上の「DOM Reference」や拙著『基礎XML』(インプレス)、『XML辞典』(翔泳社)などを参照していただきたい。

 本節におけるXMLデータ読み込み部分のコードの流れを以下の図にまとめておく。

DOMによるXMLデータの読み込み
 

 INDEX
  [特集]枯れた新しいUI革命「Ajax」をASP.NETで活用する
    1.Ajax技術の基本的な仕組みとアプリケーション例
    2.Ajax+ASP.NETによる郵便番号検索(テキスト通信)
  3.Ajax+ASP.NETによる郵便番号あいまい検索(XML通信)
    4.JavaScriptライブラリ活用で高度なAjax連携
 


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

本日 月間