Ajaxを利用してWebページがリロードされるのを回避

 

● Ajax Hello World Ajax1.aspx/SayHello.aspx

 

ASP.NETで郵便番号を入力したとき、住所をテキストボックスに表示するにはWebページをポストバックさせてページを再表示(リロード)するのが一般的です。ところが最近注目されている、Ajaxを利用するとWebページをリロードさせることなく、Webページを更新することができます。

 

Ajaxは、特に新しい技術ではなくDHTML(HTML+CSS+JavaScript)XMLHttpRequestを利用して実現することができます。

 

たとえば、AjaxWebサーバーから「Hello, AJAX!」のメッセージを取得して表示するには、ボタンのonclickイベントに「sayHello();」を追加します。

 

<input onclick="sayHello();" type="button" value="Say Hello" />

 

JavaScriptsayHello()関数で、XMLHttpRequestオブジェクトを生成したらonreadystatechangeプロパティに処理が完了したときにコールバックされるイベントハンドラを登録します。XMLHttpRequestオブジェクトのOpenメソッドでHttpリクエストの準備をしたら、Sendメソッドで送信します。Openメソッドの引数には、Httpメソッド(GET/POST)URL(SayHello.aspx)、非同期(true)/同期(false)のフラグを指定します。

 

function sayHello() {

  var url = "http://localhost/wd11/SayHello.aspx";

  req = new ActiveXObject("Microsoft.XMLHTTP");

  req.onreadystatechange = sayHelloCallBack;

  req.open("GET", url, true);

  req.send();

}

 

SayHello.aspxPage_Loadイベントハンドラでは、ResponseオブジェクトのWriteメソッドで「Hello, AJAX!」を送信します。

 

Sub Page_Load(sender As Object, e As EventArgs)

  Response.Write("Hello, AJAX!")

End Sub

 

SayHello.aspxの処理が完了すると、XMLHttpRequestのコールバックハンドラ「sayHelloCallBack」が実行されます。このイベントハンドラでは、XMLHttpRequestreadyStateプロパティに格納されているステータス(0-uninitialized, 1-loading, 2-loaded, 3-interactive, 4-complete)をチェックします。ステータスが「4-完了」のときは、さらにstausプロパティをチェックしてトランザクションが正常に終了したかどうか確認します。statusの「200」は「OK」を意味します。

 

SayHello.aspxが送信したデータは、responseTextresponseXMLプロパティに格納されています。resposneTextはテキストデータ、responseXMLXMLデータを取得するときに参照します。ここでは、テキストデータを取得しますので、responseTextに格納されている「Hello, AJAX!」を取得してalert()関数でブラウザに表示します。

 

function sayHelloCallBack() {

  if (req.readyState == 4) {

    if (req.status == 200) {

      alert(req.responseText);

    }

  }

}

 

9 ボタンをクリックしてから「Hello, AJAX!」が表示されるまでの処理の流れ(②と③の間は非同期)

 

 ①[Say Hello]ボタンをクリックするとJavaScriptsayHello()関数が実行される

 ②XMLHttpRequestopen()send()メソッドを実行してSayHello.aspxを非同期で要求

 ③ResponseWriteメソッドで「Hello, AJAX!」を送信すると、sayHelloCallBackがコールバックされる。

    XMLHttpRequestresponseTextプロパティに「Hello, AJAX!」が格納されている。

 

 

10 AjaxSayHello.aspxが送信したデータを取得して表示

 

 

リスト6 AjaxSayHello.aspxが送信したデータを取得するためのJavaScript (Ajax1.aspx)

var req;

function sayHello() {

  var url = "http://localhost/wd11/SayHello.aspx";

  req = new ActiveXObject("Microsoft.XMLHTTP");

  req.onreadystatechange = sayHelloCallBack;

  req.open("GET", url, true);

  req.send();

}

 

function sayHelloCallBack() {

  if (req.readyState == 4) {

    if (req.status == 200) {

      alert(req.responseText);

    }

  }

}

 

● Ajaxで郵便番号から住所を表示 ~Ajax4.aspx + My Ajax.NET

 

11のサンプルは、Jason Diamond氏が作成したMy Ajax.NET(Release 3)を利用して郵便番号から住所を取得して表示します(Release 5では、Ajax版のDataGridもサポートされています。Ajax.Gridコントロールについては、紙面の都合上次号にて紹介します)。

 

My Ajax.NETの最新版は、以下のサイトから無償にてダウンロードすることができます。

 

http://jason.diamond.name/weblog/

 

本誌、執筆時の最新はRelease5ですがこまめにバージョンアップされているようですから最新版をダウンロードしてください。ASP.NET対応のAjaxには、Michael Schwarz氏が開発したAjax.NETなどもありますがソースコードが非公開のようなので、今回はソースコードが公開されているMy Ajax.NETを使用します。

 

Ajax.zipを解凍したら、サブフォルダ(Ajax)に格納されているMy Ajax.NETのソースファイル「Ajax.cs」をコンパイルしてAjax.dllを作成します。ここで作成したdllは、IISの仮想ディレクトリ直下のフォルダ(bin)にコピーします。

 

csc.exe /t:library /r:System.dll,System.Web.Services.dll,System.Xml.dll Ajax.cs

 

Webページに、郵便番号、都道府県、住所のテキストボックスを作成します。郵便番号のテキストボックスには、クライアント側のイベントonblueを追加して「getAddress()」関数を呼び出します。

 

<asp:TextBox id="txtPostalCode"

  onblur="getAddress(this.value);" runat="server">

</asp:TextBox>

 

getAddress関数は、JavaScriptMy.Page.GetAddress()関数を呼び出します(JavaScriptからサーバー側のGetAddressメソッドを呼び出すための関数は自動的に生成されます)。

 

GetAddress関数の引数には、郵便番号と非同期処理が完了したときにコールバックされるイベントハンドラを指定します。My Ajax.NETが生成したGetAddress関数は、自動的にXMLHttpRequestオブジェクトを生成して、OpenSendメソッドを実行します。

 

function getAddress(postalCode) {

  My.Page.GetAddress(postalCode, doGetAddressCallBack);

}

 

Webサーバー側のGetAddressメソッドが完了すると、クライアント側のコールバックハンドラ「doGetAddressCallBack」が実行されます。このとき引数には、DataTableに格納されているデータがJSONデータ形式で返されます(JSONデータについては後述するNOTE参照)。郵便番号に対応する都道府県、市区町村、町域名は、table.Rows[0].Ken, table.Rows[0].City, table.Rows[0].Townに格納されています。table.Rows[i]に続くプロパティは、DataTableのフィールド名に対応しています。

 

My Ajax.NETを利用すると、XMLHttpRequestを意識することなく非同期処理を組み込むことができます。Webサーバー側のメソッドからは、戻り値としてテキストデータ、DataTableDataSetを返すことができます。DataTableDataSetは、自動的にJSONデータに変換されます。

 

function doGetAddressCallBack(result) {

  var table = result.value;

  document.getElementById("txtKen").value =

     table.Rows[0].Ken;

  document.getElementById("txtAddress").value =

     table.Rows[0].City + table.Rows[0].Town;

}

 

 

11: My Ajax.NETで郵便番号から住所を表示する

 

リスト7 Page_LoadイベントハンドラとGetAddressメソッドの処理 (Ajax4.aspx)

Sub Page_Load(sender As Object, e As EventArgs)

  Ajax.Manager.Register(Me, "My.Page", Ajax.Debug.None)

End Sub

 

<Ajax.Method> _

Public Function GetAddress(ByVal strPostalCode As String) As DataTable

  Dim strSQL As String = "Select Top 1 * From tblPostalCode Where Code=?"

  Dim strConnectionString As String = _

    String.Format("PROVIDER=Microsoft.Jet.OLEDB.4.0;DATA Source={0}", _

      Server.MapPath("webdb/PostalCode.mdb"))

  Dim con As New OleDbConnection(strConnectionString)

  Dim da As New OleDbDataAdapter

  Dim cmd As New OleDbCommand(strSQL, con)

  Dim dt As New DataTable()

 

  cmd.Parameters.Add("Code", strPostalCode)

  da.SelectCommand = cmd

  da.Fill(dt)

  Return dt

End Function

 

 

● Ajaxでリストボックスのアイテムを追加 ~Ajax5.aspx + My Ajax.NET

 

12のサンプルはMy Ajax.NETを利用して、ドロップダウンリストから選択した商品区分に該当する商品を、Webページをリロードすることなく非同期処理で取得してリストボックスに表示します。

 

GetProducts()関数では、DropDownListから選択した商品区分IDを取得して、My.Page.GetProducts()関数の引数に指定してサーバー側のGetProductsメソッドに渡します。

 

// DropDownListonchangeイベントハンドラ

function GetProducts(ddl) {

  if (ddl.selectedIndex >= 0) {

    var categoryID = ddl.options[ddl.selectedIndex].value;

    My.Page.GetProducts(categoryID, DoGetProductsCallBack);

  }

}

 

コールバックイベントハンドラでは、DataTableに格納されている商品データ(JSONデータ)を取得してListBoxに追加して表示します。

 

// GetProductsのコールバックイベントハンドラ

function DoGetProductsCallBack(result) {

  var select = document.getElementById("lstProducts");

  while (select.length > 0) {

    select.remove(0);

  }

  var products = result.value;

  for (var i = 0; i < products.Rows.length; ++i) {

    var option = document.createElement("option");

    option.text = products.Rows[i].ProductName;

    option.value = products.Rows[i].ProductID;

    select.add(option);

  }

}

 

 

12: 商品区分に該当する商品を非同期処理で取得してリストボックスに表示する

 

NOTE

JSONデータとは

 

DataTableに格納されているデータおよびXMLデータなどをJavaScriptから簡単に参照できるようにした特別な配列データです。JavaScriptJSONデータを定義するには、次のように記述します。

 

var myJSON = {"Rows": [

    {"text": "item1", "value": "value1"},

    {"text": "item2", "value": "value2"},

    {"text": "item3", "value": "value3"}

  ]

};

 

配列の要素を参照するには、myJSON.Rows[0].textmyJSON.Rows[0].valueのように記述します。配列のすべてのデータを取得するには、forステートメントを使用します。

 

for (var i = 0; i < myJSON.Rows.length; ++i) {

alert(myJSON.Rows[i].text);

}