■Ajaxを利用してWebページがリロードされるのを回避
● Ajax Hello World ~Ajax1.aspx/SayHello.aspx
ASP.NETで郵便番号を入力したとき、住所をテキストボックスに表示するにはWebページをポストバックさせてページを再表示(リロード)するのが一般的です。ところが最近注目されている、Ajaxを利用するとWebページをリロードさせることなく、Webページを更新することができます。
Ajaxは、特に新しい技術ではなくDHTML(HTML+CSS+JavaScript)とXMLHttpRequestを利用して実現することができます。
たとえば、AjaxでWebサーバーから「Hello, AJAX!」のメッセージを取得して表示するには、ボタンのonclickイベントに「sayHello();」を追加します。
<input onclick="sayHello();" type="button" value="Say Hello" />
JavaScriptのsayHello()関数で、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.aspxのPage_Loadイベントハンドラでは、ResponseオブジェクトのWriteメソッドで「Hello, AJAX!」を送信します。
Sub Page_Load(sender As Object, e As EventArgs)
Response.Write("Hello,
End Sub
SayHello.aspxの処理が完了すると、XMLHttpRequestのコールバックハンドラ「sayHelloCallBack」が実行されます。このイベントハンドラでは、XMLHttpRequestのreadyStateプロパティに格納されているステータス(0-uninitialized, 1-loading, 2-loaded, 3-interactive, 4-complete)をチェックします。ステータスが「4-完了」のときは、さらにstausプロパティをチェックしてトランザクションが正常に終了したかどうか確認します。statusの「200」は「OK」を意味します。
SayHello.aspxが送信したデータは、responseTextとresponseXMLプロパティに格納されています。resposneTextはテキストデータ、responseXMLはXMLデータを取得するときに参照します。ここでは、テキストデータを取得しますので、responseTextに格納されている「Hello, AJAX!」を取得してalert()関数でブラウザに表示します。
function sayHelloCallBack() {
if (req.readyState == 4) {
if (req.status == 200) {
alert(req.responseText);
}
}
}
図9: ボタンをクリックしてから「Hello, AJAX!」が表示されるまでの処理の流れ(②と③の間は非同期)

①[Say Hello]ボタンをクリックするとJavaScriptのsayHello()関数が実行される
②XMLHttpRequestのopen()とsend()メソッドを実行してSayHello.aspxを非同期で要求
③ResponseのWriteメソッドで「Hello, AJAX!」を送信すると、sayHelloCallBackがコールバックされる。
XMLHttpRequestのresponseTextプロパティに「Hello, AJAX!」が格納されている。
図10: AjaxでSayHello.aspxが送信したデータを取得して表示

リスト6: AjaxでSayHello.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
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関数は、JavaScriptのMy.Page.GetAddress()関数を呼び出します(JavaScriptからサーバー側のGetAddressメソッドを呼び出すための関数は自動的に生成されます)。
GetAddress関数の引数には、郵便番号と非同期処理が完了したときにコールバックされるイベントハンドラを指定します。My Ajax.NETが生成したGetAddress関数は、自動的にXMLHttpRequestオブジェクトを生成して、OpenとSendメソッドを実行します。
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サーバー側のメソッドからは、戻り値としてテキストデータ、DataTable、DataSetを返すことができます。DataTableとDataSetは、自動的に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メソッドに渡します。
//
DropDownListのonchangeイベントハンドラ
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から簡単に参照できるようにした特別な配列データです。JavaScriptでJSONデータを定義するには、次のように記述します。 var myJSON = {"Rows": [ {"text": "item1", "value": "value1"}, {"text": "item2", "value": "value2"}, {"text": "item3", "value": "value3"} ] }; 配列の要素を参照するには、myJSON.Rows[0]. for (var i = 0; i < myJSON.Rows.length; ++i) { alert(myJSON.Rows[i].text); } |