.NET TIPS

[ASP.NET AJAX]DynamicPopulateコントロールでXML Webサービスを非同期に呼び出すには?[2.0のみ、C#、VB]

山田 祥寛
2007/07/19

 DynamicPopulateコントロール(DynamicPopulateExtender)は、ASP.NET AJAX Control Toolkit(以降、Control Toolkit)で提供されるコントロールの1つで、あらかじめ用意されたXML Webサービス・メソッドを呼び出し、その結果でページ内の任意のコンテンツを差し替えるためのコントロールだ。

 機能的には「TIPS:[ASP.NET AJAX]クライアントサイド・スクリプトからXML Webサービスを非同期呼び出しするには?(クライアントサイド編)」で紹介したWebサービス・ブリッジ機能に似ているが、XML Webサービス・メソッドからの取得結果をただ単にページに反映させるだけであれば、DynamicPopulateコントロールを使った方がシンプルにコードが記述できる。

 逆に、XML Webサービス・メソッドからの取得結果を基に演算や加工を行いたい、あるいは、非同期通信時に複数のパラメータを送信したい、などの場合には、前掲のTIPSで紹介したWebサービス・ブリッジ機能を直接使用した方がよいだろう(後述するが、DynamicPopulateコントロールではXML Webサービス・メソッドに渡せるパラメータは1つに限られる)。

 次の画面は、DynamicPopulateコントロールを活用したサンプル・アプリケーションである。

[詳細]ボタンをクリック
DynamicPopulateコントロールを利用した書籍情報の表示
[詳細]ボタンがクリックされた書籍の詳細情報をXML Webサービスにより取得し、グリッド表下部に表示する。

 それではさっそく、DynamicPopulateコントロールを利用して、上の画面のようなサンプル・アプリケーションを作成してみよう。なお、本サンプル・プログラムを動作させるに当たっては、「TIPS:[ASP.NET AJAX]ASP.NET AJAX Control Toolkitを利用するには?」で紹介した手順に従って、Control Toolkitを利用可能な状態にしておく必要がある。

1. 書籍情報を表すBookテーブルを作成する

 まずは、ページ上に表示する書籍情報を管理するために、以下のようなBookテーブルをデータベース上に作成しておこう。

フィールド名 データ型 概要
isbn VARCHAR(30) ISBNコード(主キー)
title VARCHAR(100) 書名
description VARCHAR(MAX) 書籍の紹介文
Bookテーブルのフィールド・レイアウト

 また、Bookテーブルにはサンプル・データとして、適当な書籍情報をあらかじめセットしておくものとする。

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

 DynamicPopulateコントロールを利用するには、クライアント側からの要求に応じて何らかの処理を行い、その処理結果を文字列として返すようなXML Webサービス・クラスを用意しておく必要がある。

 以下は、クライアントから送信されたISBNコード(書籍情報を一意に表すためのコード)をキーにBookテーブルを検索し、その詳細情報を返すASP.NET Webサービス(.asmxファイル)のコードだ。

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

using System;
using System.Configuration;
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 DynamicPopulate  : System.Web.Services.WebService {

  [WebMethod()]
  public String GetBookInfo(String contextKey) {

    String result;

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

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

      // contextKeyパラメータをキーに書籍の紹介文を取得
      comm.CommandText = "SELECT description FROM Book WHERE isbn=@isbn";
      comm.Connection = db;
      DbParameter param = factory.CreateParameter();
      param.ParameterName = "@isbn";
      param.Value = contextKey;
      comm.Parameters.Add(param);
      db.Open();
      DbDataReader reader = comm.ExecuteReader();

      // 取得した情報を戻り値として返す
      //(対応するレコードが存在しない場合は
      // 固定メッセージをセット)
      if (reader.Read()) {
        result = reader["description"].ToString();
      }else{
        result = "該当する書籍情報は存在しません。";
      }
    }
    return result;
  }
}
<%@ WebService Language="VB" Class="DynamicPopulate" %>

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 DynamicPopulate
  Inherits System.Web.Services.WebService

  <WebMethod()> _
  Public Function GetBookInfo(ByVal contextKey As String) As String

    Dim result As String

    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()

      ' contextKeyパラメータをキーに書籍の紹介文を取得
      comm.CommandText = "SELECT description FROM Book WHERE isbn=@isbn"
      comm.Connection = db
      Dim param As DbParameter = factory.CreateParameter()
      param.ParameterName = "@isbn"
      param.Value = contextKey
      comm.Parameters.Add(param)
      db.Open()
      Dim reader As DbDataReader = comm.ExecuteReader()

      ' 取得した情報を戻り値として返す
      '(対応するレコードが存在しない場合は
      ' 固定メッセージをセット)
      If reader.Read() Then
        result = reader("description")
      Else
        result = "該当する書籍情報は存在しません。"
      End If
    End Using
    Return result
  End Function
End Class
クライアント側からの要求を処理するためのXML Webサービス・クラス(AutoComplete.asmx)(上:C#、下:VB)

 サンプル・アプリケーションの大まかな流れについては、コード内のコメントを参照していただくとして、ここで注目していただきたいのは、以下の2点だ(なお、ここではXML Webサービス・クラスそのものの記法については割愛する。詳細については、「ASP.NETを使用したXML Webサービス」を参照していただきたい)。

(1)XML Webサービス・クラスにはScriptService属性を付与する

 ScriptService属性(System.Web.Script.Services名前空間)は、該当のXML Webサービス・クラスがクライアント側スクリプトから呼び出し可能であるかどうかを表すものだ。

 DynamicPopulateコントロールは(ほかの多くのExtender系のコントロールと同様に)内部的に自動生成したJavaScript経由でサーバ側のXML Webサービスと非同期通信を行うので、通信先となるXML Webサービス・クラスでは必ずScriptService属性を付与しておく必要がある。

(2)XML Webサービス・メソッドのパラメータ名、戻り値の型は固定

 DynamicPopulateコントロールにおいて、XML Webサービス・メソッドの名前は自由に決めることができるが(ここではGetBookInfo)、戻り値のデータ型およびパラメータの名前/データ型は完全に固定であり、アプリケーション開発者が変更することはできない。

 つまり、いかなる場合にもXML Webサービス・メソッドは以下のシグニチャに従う必要がある。C#/Visual Basic(VB)いずれを利用しているかにかかわらず、パラメータの名前は大文字/小文字まで厳密に区別されるので、注意してほしい。

[WebMethod()]
public String <メソッド名>(String contextKey)
<WebMethod()> _
Public Function <メソッド名>(ByVal contextKey As String) As String
DynamicPopulateコントロールから呼び出されるXML Webサービス・メソッドのシグニチャ(上:C#、下:VB)

 XML Webサービス・メソッドがcontextKeyパラメータを介して受け取るのは、クライアント側からの任意のキー値だ。DynamicPopulateコントロールでは、このcontextKeyパラメータの値をキーに、処理を分岐したり、データベースなどへの問い合わせをしたりすることができる。後述するように、本サンプルではcontextKeyパラメータとして、書籍情報を一意に特定するISBNコードがセットされているものとする。

 なお、DynamicPopulateコントロールでは、XML Webサービス・メソッドのシグニチャの制限から、クライアントからは1つしかパラメータを受け取ることができない。もちろん、特定の区切り文字で連結した文字列を生成し、疑似的に複数のパラメータを表現するといったことは可能であるが、それにしてもコードの可読性/保守性をかんがみれば、あまりに複雑なパラメータ情報を引き渡すのは好ましくないだろう。

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

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

Webフォーム(DynamicPopulate.aspx)のレイアウト
プロパティの設定内容は以下のとおり。GridViewコントロールのオートフォーマットは「シンプル」を設定。
コントロール(ID) プロパティ 設定値
ScriptManager(manager)
GridView(grid)
Label(lblResult) BackColor #FFFFC0
BorderColor #400000
BorderStyle Solid
BorderWidth 1px

 ここで、GridViewコントロールに表示すべきデータソースの内容を定義しておく必要がある。データソースを定義するには、いま配置したGridViewコントロールの右上から[GridViewタスク]メニューを表示して[データソースの選択]を選択すればよい。

[データソース構成ウィザード]ダイアログ
GridViewコントロールの右上から[GridViewタスク]メニューを表示して[データソースの選択]から「<新しいデータソース>」を選択することで、このダイアログが表示される。

 上の画面のような[データソース構成ウィザード]ダイアログが起動するので、以下の表の要領でデータソースの取得に必要な情報を設定する。データソース構成ウィザードの詳細については、「無償データベース SQL Server 2005 Express Editionを使ってみよう」が詳しいので、こちらも併せて参照していただきたい。

項目 概要
データの種類 データベース
データソースID sds
データ接続の選択 MyDB
テーブル Book
isbn、titleにチェック
データソース構成ウィザードの設定

4. GridViewコントロールの列を編集する

 GridViewコントロールの表示列を編集するには、コントロール右肩のタスク・メニューから[列の編集]を選択する。

[フィールド]ダイアログ

 [フィールド]ダイアログが開くので、以下の表に従って列情報を入力する。フィールド編集に関しては、「データアクセス/データソース・コントロールを使い倒せ!」が詳しいので、併せて参照していただきたい。

フィールド プロパティ名 概要
BoundField HeaderText 書名
DataField title
SortExpression title
TemplateField HeaderText 詳細
フィールド情報の設定

 TemplateFieldフィールドのレイアウト/プロパティは、以下の画面/表のように編集するものとする。TemplateFieldフィールドのテンプレート編集を行うには、GridViewコントロールのタスク・メニューから[テンプレートの編集]を選択する。フォーム・デザイナ上の表示が、テンプレート編集モードに切り替わるので、タスク・メニューから編集したいテンプレート(ここでは[Column[1] - 詳細]−[ItemTemplate])を選択すればよい。

[Column[1] - 詳細]−[ItemTemplate]テンプレートのレイアウト
プロパティの設定内容は以下のとおり。
コントロール(ID) プロパティ 設定値
Button(btnUpdate) OnClientClick return false;
Text 詳細
DynamicPopulateExtender(dpex) BehaviorID* Eval("isbn")
ContextKey* Eval("isbn")
PopulateTriggerControlID btnUpdate
ServiceMethod GetBookInfo
ServicePath DynamicPopulate.asmx
TargetControlID lblResult
UpdatingCssClass dynamicPopulate_Updating
[参考]
上の表で「*」が付いているプロパティの値はバインド式となっており、プロパティ・ウィンドウから直接に入力することはできないので、注意すること。バインド式の入力には、コントロール右肩のタスク・メニューから[DataBindingsの編集]を選択し、表示された[<コントロール名> DataBindings]ダイアログから[カスタムバインド]−[コード式]欄に入力する必要がある(バインド式の詳細については、「テンプレート機能でGridViewコントロールも自由自在」を参照)。

[<コントロール名> DataBindings]ダイアログ

[注意]

非同期通信のトリガーとして、ASP.NETのボタン系コントロール(Button、LinkButton、ImageButton)を利用する場合には、クリックのタイミングでポストバックが発生しないよう、OnClientClickプロパティに「return false;」と指定し、クリック・イベントを明示的にキャンセルしている点に注目してほしい。この指定がない場合には、画面全体がリフレッシュされてしまい、非同期通信の結果は正しく反映されないので注意すること。

DynamicPopulateコントロールのTargetControlIDプロパティは、XML Webサービス・メソッドによる自動更新機能を付与するサーバ・コントロールを指定するものだ。ここでは、LabelコントロールlblResultに対してDynamicPopulateコントロールの機能が追加されたことになるわけだ。

 なお、DynamicPopulateコントロールのそのほかのプロパティを設定する場合、(DynamicPopulateコントロールではなく)関連付けたサーバ・コントロールのプロパティとして設定する必要がある点に注意してほしい。本稿の場合であれば、Labelコントロールのプロパティ・ウィンドウに「grid.Column1.ItemTemplate.dpex(DynamicPopulateExtender)」という項目が追加されているので、この項目の配下から個々の値を設定する。

 DynamicPopulateコントロールで利用可能な主なプロパティは、以下のとおりだ。

プロパティ名 概要
TargetControlID 関連付けるサーバ・コントロール
BehaviorID コントロールの挙動設定を識別するためのID値
ClearContentsDuringUpdate 非同期通信を開始したタイミングで更新対象となる要素の中身をクリアするか(デフォルトはTrue)
ServicePath クライアントからの要求に応じて処理を行うXML Webサービス(.asmxファイル)のパス
ServiceMethod クライアントからの要求に応じて処理を行うXML Webサービス・メソッドの名前
PopulateTriggerControlID 非同期通信のトリガーとなるコントロールのID値
UpdatingCssClass 非同期通信中にターゲットに適用するCSSクラスの名前
CustomScript XML Webサービス・メソッドの代わりに呼び出されるスクリプト
ContextKey XML Webサービス・メソッドで問い合わせに使用するための任意のキー値
DynamicPopulateコントロールの主なプロパティ

 多くのプロパティが用意されているが、最低限、設定が必要なのは値リストを取得するためのXML Webサービス・メソッドを特定するServicePath/ServiceMethodプロパティと、XML Webサービス・メソッド上で処理を分岐するためのキーを表すContextKeyプロパティだ。ここでは、ContextKeyプロパティに、Bookテーブルから取得したisbnフィールドの値をバインドすることで、XML Webサービス・メソッドから詳細情報を取得する際のキーとしているわけだ。

 なお、UpdatingCssClassプロパティではdynamicPopulate_Updatingという名前のCSSクラスを指定しているが、これはControl Toolkitで提供されているサンプル・アプリケーションに含まれている.cssファイルで定義されているクラスだ。スタイルシートの引用については、「TIPS:[ASP.NET AJAX]ASP.NET AJAX Control Toolkitを利用するには?」でも紹介しているので、併せて参照していただきたい。

 以上で、画面の外観にかかわる設定は完了だ。ここで参考までにVisual Studio 2005によって自動生成されたコードを引用しておく。

<%--Control Toolkitを使用する場合には先頭にScriptManagerの配置は必須--%>
<asp:ScriptManager ID="manager" runat="server">
  </asp:ScriptManager>
<asp:GridView ID="grid" runat="server" CellPadding="4" DataSourceID="sds"
  ForeColor="#333333" GridLines="None" AutoGenerateColumns="False">
  <FooterStyle BackColor="#1C5E55" Font-Bold="True" ForeColor="White" />
  <RowStyle BackColor="#E3EAEB" />
  <EditRowStyle BackColor="#7C6F57" />
  <SelectedRowStyle BackColor="#C5BBAF" Font-Bold="True"

ForeColor="#333333" />
  <PagerStyle BackColor="#666666" ForeColor="White"

HorizontalAlign="Center" />
  <HeaderStyle BackColor="#1C5E55" Font-Bold="True" ForeColor="White" />
  <AlternatingRowStyle BackColor="White" />
  <Columns>
    <asp:BoundField DataField="title" HeaderText="書名"
      SortExpression="title" />
    <%--「詳細」列のテンプレート定義--%>
    <asp:TemplateField>
      <ItemTemplate>
        <asp:Button ID="btnUpdate" runat="server"
          OnClientClick="return false;" Text="詳細" />
        <%--[詳細]ボタンとグリッド表下部のラベルとの関連付け--%>
        <ajaxToolkit:DynamicPopulateExtender ID="dpex" runat="server"
          BehaviorID='<%# Eval("isbn") %>'
          ContextKey='<%# Eval("isbn") %>' Enabled="True"
          PopulateTriggerControlID="btnUpdate"
          ServiceMethod="GetBookInfo" ServicePath="DynamicPopulate.asmx"
          TargetControlID="lblResult"
          UpdatingCssClass="dynamicPopulate_Updating">
        </ajaxToolkit:DynamicPopulateExtender>
      </ItemTemplate>
    </asp:TemplateField>
  </Columns>
</asp:GridView>
<asp:SqlDataSource ID="sds" runat="server"
  ConnectionString="<%$ ConnectionStrings:MyDB %>"
  SelectCommand="SELECT [isbn], [title] FROM [Book]"></asp:SqlDataSource>
<asp:Label ID="lblResult" runat="server" BackColor="#FFFFC0"
  BorderColor="#400000" BorderStyle="Solid" BorderWidth="1px"></asp:Label>
DynamicPopulate.aspxのソース・コード(抜粋)
一連のレイアウト編集を行った後、Visual Studio 2005によって自動生成されたコードを引用したもの。なお、<%--〜--%>は筆者によるコメント。

 以上を理解したら、さっそく作成したサンプル・プログラムを実行してみよう。冒頭の画面のように、グリッド上の各[詳細]ボタンをクリックすることで、表の下部に対応する書籍情報が表示されれば成功だ。End of Article

利用可能バージョン:.NET Framework 2.0のみ
カテゴリ:Webフォーム 処理対象:ASP.NET AJAX
使用ライブラリ:DynamicPopulateコントロール
関連TIPS:[ASP.NET AJAX]ASP.NET AJAX Control Toolkitを利用するには?
関連TIPS:[ASP.NET AJAX]クライアントサイド・スクリプトからXML Webサービスを非同期呼び出しするには?(クライアントサイド編)

この記事と関連性の高い別の.NET TIPS
[ASP.NET AJAX]ダイナミック・コンテキスト機能でポップアップ・コントロールの内容を動的に生成するには?
[ASP.NET AJAX]AutoCompleteコントロールでGoogleサジェスト風なオートコンプリート機能を実装するには?
[ASP.NET AJAX]クライアントサイド・スクリプトからXML Webサービスを非同期呼び出しするには?(サーバサイド編)
[ASP.NET AJAX]Webサービス・ブリッジ機能により構造化データを受け渡しするには?(基本編)
[ASP.NET AJAX]NumericUpDownコントロールでアップダウン・ボタンを生成するには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム 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 記事ランキング

本日 月間