.NET TIPS

[ASP.NET]ページを再読み込みせずにサーバと通信を行うには?[2.0のみ、C#、VB]

山田 祥寛
2006/05/19

 いまさらあらためて述べるまでもなく、ASP.NETはイベント駆動モデルをベースとしたフレームワークだ。イベント駆動モデルの導入によって、開発者は限りなくWindowsアプリケーション的な要領で、Webアプリケーションを構築できるようになった。もっとも、Windowsアプリケーション<的>というところが落とし穴で、ASP.NETで提供されるイベント駆動モデルはWindowsフォームで提供されるそれとは、厳密には等しくないことを理解しておく必要がある。

 というのも、Windowsアプリケーションにおいて、クライアント上で発生したイベントは原則としてクライアントで処理される。しかし、ASP.NETのWebフォームでは、クライアント上で発生したイベントは、いったんサーバ側にポストバックされたうえで、サーバ側で処理される。そして、サーバ側で処理した結果を基に、ページ全体をもう一度描画し直すというわけだ。

 このようなポストバック処理が負荷の高いものであることは、直感的にもご理解いただけるであろう。また、イベントが発生するたびにページ全体をリフレッシュすることから、エンドユーザーにとっても作業が途中で中断される、画面がちらつくなど、ストレスを感じること甚だしい。

ASP.NETにおけるイベント処理の仕組み
ASP.NETではイベント処理を行うために、必ずサーバへのポストバックを行わなければならない。

 そこで登場するのが、ASP.NET 2.0から導入された「クライアント・コールバック」だ。クライアント・コールバックとは、XML HTTP(=HTTPベースでXML形式のデータをやりとりする方法)によって実現できるコールバック処理のことで、これを利用することで、イベント処理のたびにページ全体をリフレッシュする必要がなくなる。

 XML HTTPによるコールバックでは、サーバへのリクエストはJavaScriptなどのクライアントサイド・スクリプトから発行され、その結果もクライアントサイド・スクリプトの関数によって受け取ることができる。

 クライアント・コールバックでは、この仕組みを利用することで、イベント発生時に必要なデータだけをサーバに送信し、その応答に基づいて、ページ上の「必要な個所」だけを変更できるというわけだ。例えば、大きなページでごく一部のコンテンツだけを更新したいという場合には、クライアント・コールバックを利用することで、大幅なパフォーマンスの改善が望めるだろう。

 それでは実際に、クライアント・コールバックを利用した例を見てみよう。以下の画面は、左のテキストボックスにISBNコードを入力し、[検索]ボタンをクリックすることで、右のテキストボックスに対応する書籍名を表示する、ごく単純な書籍検索のためのアプリケーションの実行例だ。

クライアント・コールバックを利用した書籍検索の例
左のテキストボックスにISBNコードを入力し、[検索]ボタンをクリックすると、右のテキストボックスに対応する書籍名を表示する。この処理の過程でポストバックは行われない。

 具体的なコードは、以下のとおりだ。

<%@ Page Language="C#" %>
<%@ Implements Interface="System.Web.UI.ICallbackEventHandler" %>
<script runat="server">
// コールバック処理の結果を格納するためのプライベート変数
private String result;

// クライアントから送信されたISBNコードの値に応じて書名を検索
public void RaiseCallbackEvent(String arg) {
  switch(arg){
    case "4-7980-1297-1":
      this.result = "Pocket詳解Perl/CGI辞典";
      break;
    case "4-7981-1070-1":
      this.result = "XMLデータベース入門";
      break;
    case "4-7981-0371-3":
      this.result = "独習ASP.NET";
      break;
    default:
      this.result = "不明";
      break;
  }
}

// クライアントに対して結果データを応答

public String GetCallbackResult(){
  return this.result;
}

// クライアント関数への参照を取得し、Buttonコントロールに登録
protected void Page_Load(Object sender, EventArgs e){
  String ceRef =
    Page.ClientScript.GetCallbackEventReference(
      this,
      "document.getElementById('txtIsbn').value",
      "cbResult",
      "null");
  btnSrch.OnClientClick = ceRef + ";return false;";
}
</script>
<html>
<head>
<title>クライアントコールバック</title>
<script language="javascript" type="text/javascript">
<!--
// サーバから送信された値をテキストボックスtxtNameにセット
function cbResult(result, context) {
  document.getElementById('txtName').value = result;
}
//-->
</script>
</head>
<body>
<form id="Form1" runat="server">
ISBNコード:<asp:TextBox ID="txtIsbn" runat="server" Columns="18" />
<asp:Button ID="btnSrch" runat="server" Text="検索" />
<asp:TextBox ID="txtName" runat="server" Columns="25" />
</form>
</body>
</html>
クライアント・コールバックを実装したWebフォーム(C#版:callback_cs.aspx)
 
<%@ Page Language="VB" %>
<%@ Implements Interface="System.Web.UI.ICallbackEventHandler" %>
<script runat="server">
' コールバック処理の結果を格納するためのプライベート変数
Private result As String

' クライアントから送信されたISBNコードの値に応じて書名を検索
Public Sub RaiseCallbackEvent(ByVal arg As String) Implements System.Web.UI.ICallbackEventHandler.RaiseCallbackEvent
  Select Case arg
    Case "4-7980-1297-1" : Me.result = "Pocket詳解Perl/CGI辞典"
    Case "4-7981-1070-1" : Me.result = "XMLデータベース入門"
    Case "4-7981-0371-3" : Me.result = "独習ASP.NET"
    Case Else : Me.result = "不明"
  End Select
End Sub

' クライアントに対して結果データを応答
Public Function GetCallbackResult() As String Implements System.Web.UI.ICallbackEventHandler.GetCallbackResult
  Return Me.result
End Function

' クライアント関数への参照を取得し、Buttonコントロールに登録
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
  Dim ceRef As String = _
    Page.ClientScript.GetCallbackEventReference( _
      Me, _
      "document.getElementById('txtIsbn').value", _
      "cbResult", _
      "null")
  btnSrch.OnClientClick = ceRef & ";return false;"
End Sub
</script>
<html>
<head>
<title>クライアントコールバック</title>
<script language="javascript" type="text/javascript">
<!--
// サーバから送信された値をテキストボックスtxtNameにセット
function cbResult(result,context) {
  document.getElementById('txtName').value = result;
}
//-->
</script>
</head>
<body>
<form runat="server">
ISBNコード:<asp:TextBox ID="txtIsbn" runat="server" Columns="18" />
<asp:Button ID="btnSrch" runat="server" Text="検索" />
<asp:TextBox ID="txtName" runat="server" Columns="25" />
</form>
</body>
</html>
クライアント・コールバックを実装したWebフォーム(VB版:callback_vb.aspx)

 クライアント・コールバックを利用するための条件は以下の3点だ。

(1)ICallbackEventHandlerインターフェイスを実装する

 クライアント・コールバック機能を利用するには、@ImplementsディレクティブでICallbackEventHandlerインターフェイス(System.Web.UI名前空間)を実装する必要がある。

 ICallBackEventHandlerインターフェイスで定義されたメソッドは、RaiseCallbackEventメソッドとGetCallbackResultメソッドだ。

 RaiseCallbackEventメソッドは、コールバックによる実処理を規定するためのメソッドである。このメソッドは、クライアント側でボタンがクリックされたタイミングでクライアントサイド・スクリプトから呼び出されることになる。

 本稿のサンプル・プログラムでは、ただ単に送信されたISBNコードに基づいて、ハード・コーディングされたデータから対応する書名を取得しているにすぎないが、実際のアプリケーションではここでデータベースなどへの問い合わせが発生するはずだ。RaiseCallbackEventメソッドによる処理結果は、ページ内で定義されたプライベート変数に格納する。格納されたプライベート変数の内容は、GetCallbackResultメソッドによって、実際にクライアント側に返される。

(2)GetCallbackEventReferenceメソッドでクライアント関数への参照を取得する

 クライアント・コールバックを実行するには、ClientScriptManager.GetCallbackEventReferenceメソッドで、クライアントサイド・スクリプトによる関数への参照を取得する必要がある。GetCallbackEventReferenceメソッドの構文は以下のとおり。

GetCallbackEventReference(
  ICallbackEventHandlerインターフェイスを実装したコントロール,
  RaiseCallBackメソッドに渡す値を表すクライアントサイド・スクリプト,
  コールバック関数の名前(クライアントサイド・スクリプトで定義),
  コールバック関数に引き渡すコンテキスト値
)
GetCallbackEventReferenceメソッドの構文

 第4パラメータで表されるコンテキスト値は、呼び出し元を特定するための任意のキー値を表す。クライアント・コールバックが複数の個所から利用されている場合には、このコンテキスト値を利用することで、呼び出し元を識別することができる。本サンプル・プログラムのように、クライアント・コールバックの発生元とコールバック関数の関係が1対1であるならば、固定値でnullを指定すればよい。

 GetCallbackEventReferenceメソッドの実行によって、クライアント・コールバックの呼び出しに必要なJavaScriptのコードが生成されるので、後はこれをButtonコントロール「btnSrch」のクライアント側のClickイベントに登録するだけだ。ASP.NET 2.0では、クライアント側のClick属性にイベントハンドラを登録するために、OnClientClickプロパティが追加されたので、本稿でもこれを利用している。

 なお、GetCallbackEventReferenceメソッドによって生成されたJavaScriptコードの末尾には、必ず「return false;」という1文を追加し、明示的にクリック・イベントの発生を抑制すること。この1文がない場合には、デフォルトでButtonコントロールはサーバへのポストバックを発生させるため、クライアント・コールバックが正常に動作しない。

(3)クライアント側の処理関数を定義する

 クライアント・コールバックでは、サーバ側から結果が返されたときにページ上の必要な個所を動的に更新するために、クライアント側で実行可能なJavaScriptの関数(コールバック関数)を用意しておく必要がある。本サンプル・プログラムでコールバック関数に相当するのがcbResult関数だ。関数名は(2)で示したGetCallbackEventReferenceメソッドの第2パラメータと対応してさえいれば、自由に決めて構わない。

 コールバック関数は、第1パラメータとしてGetCallbackResultメソッドからの処理結果を、第2パラメータとしてGetCallbackEventReferenceメソッドで指定されたコンテキスト値を受け取る。ここでは、サーバ側から受け取った処理結果をそのままテキストボックス「txtName」に表示しているというわけだ。

 以上を理解したら、さっそくサンプル・プログラムを実行してみよう。冒頭で示した画面と同じように、入力したISBNコードに応じて対応する書名がテキストボックス上に表示されれば成功だ。この検索処理に際して、ページ全体をリフレッシュして<いない>点に注目していただきたい。End of Article

利用可能バージョン:.NET Framework 2.0のみ
カテゴリ:Webフォーム 処理対象:クライアント・コールバック
使用ライブラリ:ICallbackEventHandlerインターフェイス(System.Web.UI名前空間)

この記事と関連性の高い別の.NET TIPS
[ASP.NET AJAX]クライアントサイド・スクリプトからXML Webサービスを非同期呼び出しするには?(クライアントサイド編)
[ASP.NET]Ajax.NETでAjaxプログラミングを効率化するには?
[ASP.NET AJAX]Webサービス・ブリッジ機能により構造化データを受け渡しするには?(基本編)
[ASP.NET]ポストとポストバックの違いは?
[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 記事ランキング

本日 月間