.NET TIPS

[ASP.NET AJAX]Webサービス・ブリッジ機能により構造化データを受け渡しするには?(基本編)[2.0のみ、C#、VB]

山田 祥寛
2007/07/05

 以下の2つのTIPSでは、ASP.NET AJAXのWebサービス・ブリッジ機能を利用して、クライアントサイド・スクリプトからXML Webサービス・クラスを呼び出す方法について紹介した。

 ASP.NET AJAXが自動生成するプロキシ・クラスを経由することで、XMLHttpRequestオブジェクトなどの原始的な通信手続きをほとんど意識することなく、クライアント/サーバ間の非同期通信を実現できるのがうれしいポイントだ。

 前掲の2つのTIPSでは、まずWebサービス・ブリッジ機能の基本的な動作を確認するという意味も込めて、ごく単純な結果文字列を受け取るサンプルを紹介したわけであるが、これだけならば、何もASP.NET AJAXを持ち出さなくても、ASP.NET 2.0標準のクライアント・コールバック機能でも実現が可能だ(詳細は「TIPS:[ASP.NET]ページを再読み込みせずにサーバと通信を行うには?」)。

 しかし、クライアント・コールバック機能とASP.NET AJAXのWebサービス・ブリッジ機能が大きく異なる点は、Webサービス・ブリッジ機能が、いわゆるスカラー値(単一値)だけではなく、配列/オブジェクトのような構造データをクライアント/サーバ間でやりとりできるという点だ。本稿では、その具体的な方法を紹介する。

 ここで紹介するサンプル・アプリケーションは、「枯れた新しいUI革命『Ajax』をASP.NETで活用する」でも紹介した郵便番号あいまい検索アプリケーションを、ASP.NET AJAXを使って書き直したものだ。標準的なASP.NET+JavaScriptで記述した場合と比べ、こちらのコードがいかに簡素化されるかを見てみるのもよいだろう。

郵便番号「184」を入力
「184002 東京都小金井市梶野町」をクリック
テキストボックスに「東京都小金井市梶野町」が入力される
ASP.NET AJAXを利用した住所検索アプリケーション(あいまい検索対応)
画面左のテキストボックスに3けた以上の郵便番号を入力すると、フォーム下部に該当する住所情報の上位15件をリスト表示する。リスト表示された住所情報をクリックすると、その内容をフォーム(上記画面のテキストボックス)に反映することができる。

 それでは具体的なコードを見ていくことにしよう。なお、本サンプルの動作に当たっては、前掲のTIPSのサーバサイド編/クライアントサイド編で紹介した住所情報テーブル(addressテーブル)を作成し、あらかじめ必要なデータをセットアップしておく必要がある。

1. 新規のXML Webサービス・クラスを定義する

 ASP.NET AJAXにおいてサーバサイドの機能を提供するのは.asmxファイル(XML Webサービス・クラス)の役割だ。ここでは、クライアント・ページから送信された郵便番号(postnumパラメータ)をキーに、addressテーブルを前方一致検索し、合致した住所情報を文字列として返すXML Webサービス・クラス(ServiceBridge.asmx)を定義してみよう。このServiceBridge.asmxの具体的なコードは、以下のとおり。

<%@ WebService Language="C#" Class="ServiceBridge" %>

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.Common;
using System.Web;
using System.Web.Script.Services;
using System.Web.Services;
using System.Web.Services.Protocols;

[WebService(Namespace="http://tempuri.org/")]
[WebServiceBinding(ConformsTo=WsiProfiles.BasicProfile1_1)]
[ScriptService()]
public class ServiceBridge : System.Web.Services.WebService {

  [WebMethod()]
  public AddressData[] GetAddressesByPostnum(String postnum) {

    List<AddressData> result = new List<AddressData>();

    ConnectionStringSettings setting =
      ConfigurationManager.ConnectionStrings["MyDB"];
    DbProviderFactory factory =
      DbProviderFactories.GetFactory(setting.ProviderName);

    using (DbConnection db = factory.CreateConnection()) {
      db.ConnectionString = setting.ConnectionString;
      DbCommand comm = factory.CreateCommand();

      // postnumパラメータをキーに住所情報を前方一致検索
      comm.CommandText = "SELECT postnum, prefecture, city, other FROM Address WHERE postnum LIKE @postnum";
      comm.Connection = db;
      DbParameter param = factory.CreateParameter();
      param.ParameterName = "@postnum";
      param.Value = postnum + "%";
      comm.Parameters.Add(param);
      db.Open();
      DbDataReader reader = comm.ExecuteReader();

      // 取得した県、市、そのほかの情報を連結し、
      // その値をリストに追加
      while (reader.Read()) {
        AddressData data = new AddressData();
        data.Postnum = reader["postnum"].ToString();
        data.Address = reader["prefecture"].ToString()
             + reader["city"].ToString() + reader["other"].ToString();
        result.Add(data);
      }
    }

    // リストを配列(AddressDataオブジェクト配列)に変換
    return result.ToArray();
  }
}

// 住所情報を格納するためのAddressDataクラスを定義
public class AddressData {
  public String Postnum;
  public String Address;
}
<%@ WebService Language="VB" Class="ServiceBridge" %>

Imports System.Collections.Generic
Imports System.Data
Imports System.Data.Common
Imports System.Web
Imports System.Web.Script.Services
Imports System.Web.Services
Imports System.Web.Services.Protocols

<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<ScriptService()> _
Public Class ServiceBridge
  Inherits System.Web.Services.WebService

  <WebMethod()> _
  Public Function GetAddressesByPostnum(ByVal postnum As String) As AddressData()

    Dim result As New List(Of AddressData)

    Dim setting As ConnectionStringSettings = _
      ConfigurationManager.ConnectionStrings("MyDB")
    Dim factory As DbProviderFactory = _
      DbProviderFactories.GetFactory(setting.ProviderName)

    Using db As DbConnection = factory.CreateConnection()
      db.ConnectionString = setting.ConnectionString
      Dim comm As DbCommand = factory.CreateCommand()

      ' postnumパラメータをキーに住所情報を前方一致検索
      comm.CommandText = "SELECT postnum, prefecture, city, other FROM Address WHERE postnum LIKE @postnum"
      comm.Connection = db
      Dim param As DbParameter = factory.CreateParameter()
      param.ParameterName = "@postnum"
      param.Value = postnum & "%"
      comm.Parameters.Add(param)
      db.Open()
      Dim reader As DbDataReader = comm.ExecuteReader()

      ' 取得した県、市、そのほかの情報を連結し、
      'その値をリストに追加
      Do While reader.Read()
        Dim data As New AddressData()
        data.Postnum = reader("postnum")
        data.Address = reader("prefecture") & reader("city") & reader("other")
        result.Add(data)
      Loop
    End Using

    ' リストを配列(AddressDataオブジェクト配列)に変換
    Return result.ToArray()
  End Function
End Class

' 住所情報を格納するためのAddressDataクラスを定義
Public Class AddressData
  Public Postnum As String
  Public Address As String
End Class
郵便番号をキーに対応する住所を前方一致検索するためのXML Webサービス・クラス(ServiceBridge.asmx)(上:C#、下:VB)

 Webサービス・ブリッジ機能を利用するうえで必要な基本構文については、上述の「クライアントサイド編」を参照いただくとして、ここであえて特筆すべき点があるとしたら、

「構造データをやりとりするといっても、ことさら特別な手順は必要ない」

という点だ。単純なスカラー値をやりとりするのとまったく同じ要領で、サービス・メソッドを定義できる。

2. 新規のWebフォームを作成する

 新規のWebフォーム(ServiceBridge2.aspx)を作成したら、フォーム・デザイナから以下の画面の要領でサーバ・コントロールを配置する。また、それぞれのコントロールに対しては、表の内容でプロパティ値を設定しておこう。

Webフォーム(ServiceBridge2.aspx)のレイアウト
各コントロールのプロパティ内容は以下のとおり。
コントロール(ID) プロパティ 設定値
ScriptManager(manager) Services ServiceBridge.asmx(設定方法は「クライアントサイド編を参照)
Input<Text>(postnum) Size 10
onkeyup* return postnum_onkeyup()
input<Text>(address) Size 50
Div(result)
* onkeyupプロパティはプロパティ・ウィンドウからは設定できない。設定を行うには、コードエディタ上部の選択ボックスから「postnum(コントロールのID値)」−「onkeyup」と選択する必要がある。

 (idが「result」の)<div>タグは、サービス・メソッド経由で取得した住所リストを表示するために用意した領域だ。

 なお参考までに、ここまでにVisual Studio 2005で自動生成されたコードを引用しておく。<%--〜--%>は筆者によるコメントである。

<%--ASP.NET AJAXを使用する場合には先頭にScriptManagerの配置は必須--%>
<asp:ScriptManager ID="manager" runat="server">
  <%--.asmxファイルをサービスとして登録--%>
  <Services>
    <asp:ServiceReference Path="ServiceBridge.asmx" />
  </Services>
</asp:ScriptManager>
郵便番号検索<br /><br />
郵便番号:
<input id="postnum" size="10" type="text"
  language="javascript" onkeyup="return postnum_onkeyup()" />
<input id="address" size="50" type="text" />
<div id="result" />
ServiceBridge.aspxのソース・コード(抜粋)
一連のレイアウト編集を行った後、Visual Studio 2005によって自動生成されたコードを引用したもの。

3. サービス呼び出しのコードを記述する

 あとは、ScriptManagerコントロールによって自動生成されたプロキシ・クラスを介して、サービス・メソッドを呼び出すJavaScriptのコードを記述するだけだ。具体的なコードは、以下のとおり。

<script language="javascript" type="text/javascript">
<!--
// postnum_onkeyup関数は、エンド・ユーザーが
// テキストボックスpostnum上でキーを押下し、
// 離したタイミングで呼び出される
function postnum_onkeyup() {

  // [郵便番号]欄に2文字以上入力されていたら、
  // サービス・メソッドを呼び出し
  if ($get('postnum').value.length > 2) {

    var contents;

    ServiceBridge.GetAddressesByPostnum(
      $get('postnum').value,
      // 成功コールバック
      // 取得したオブジェクト配列からHTMLのリストを生成
      function(result) {
        contents = "<ol type='square'>";
        for (i =0; i < result.length; i++) {
          contents += "<li><a href='JavaScript: void(0)' onclick=\"document.fm.postnum.value="
          + result[i]['Postnum']
          + ";document.fm.address.value='"
          + result[i]['Address']
          + "';\">"
          + result[i]['Postnum']
          + "&nbsp;"
          + result[i]['Address']
          + "</a></li>";
        }
        contents+="</ol>";
        // 生成したリストを<div>タグ(id「result」)に反映
        $get('result').innerHTML=contents;
      },
      // 例外コールバック。例外メッセージを[住所]欄にセット
      function(ext) { $get('address').value = ext.get_message(); }
    );
  }
}
// -->
</script>
プロキシ・クラス経由でサービス・メソッドにアクセスするコード(ServiceBridge2.aspx)

 ServiceBridge.GetAddressesByPostnumメソッドの成功コールバックに注目してみよう。GetAddressesByPostnumメソッドの戻り値であるAddressDataオブジェクト配列にアクセスするには、以下のように記述するだけでよい。

result[i]['Address']

 これによって、i番目のAddressDataオブジェクト配列のAddressプロパティの値を取得できるというわけだ。「枯れた新しいUI革命『Ajax』をASP.NETで活用する」でも紹介した同等のサンプルと比べ、煩雑なDOMアクセスがない分、はるかに直感的に記述できることがお分かりになるはずだ。

 以上を理解したら、さっそく作成したサンプル・プログラムを実行してみよう。冒頭の画面のように、左のテキストボックスに文字を入力すると、それに対応する住所情報がページ下部にリスト表示されることが確認できれば成功だ。End of Article

利用可能バージョン:.NET Framework 2.0のみ
カテゴリ:Webフォーム 処理対象:ASP.NET AJAX
関連TIPS:[ASP.NET AJAX]クライアントサイド・スクリプトからXML Webサービスを非同期呼び出しするには?(サーバサイド編)
関連TIPS:[ASP.NET AJAX]クライアントサイド・スクリプトからXML Webサービスを非同期呼び出しするには?(クライアントサイド編)
関連TIPS:[ASP.NET]ページを再読み込みせずにサーバと通信を行うには?

この記事と関連性の高い別の.NET TIPS
[ASP.NET AJAX]クライアントサイド・スクリプトからXML Webサービスを非同期呼び出しするには?(サーバサイド編)
[ASP.NET AJAX]ダイナミック・コンテキスト機能でポップアップ・コントロールの内容を動的に生成するには?
[ASP.NET AJAX]DynamicPopulateコントロールでXML Webサービスを非同期に呼び出すには?
[ASP.NET AJAX]クライアントサイド・スクリプトからXML Webサービスを非同期呼び出しするには?(クライアントサイド編)
[ASP.NET AJAX]クライアントサイド・スクリプトからASP.NETのプロファイル機能を利用するには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム 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 記事ランキング

本日 月間