#contents *ASP.NETでAjaxを使用したWebアプリケーションを作成する 1 [#p66b658c] 「.NETプログラミング研究」の第76号で予告したとおり(かなり間が開いてしまいましたが)、今回から何回かに分けてASP.NETでAjaxを使ったWebアプリケーションを作成する方法を紹介します。今回は、.NETの機能を全く使用しない方法を紹介します。今後は、.NET Framework 2.0から追加されたICallbackEventHandlerインターフェイスを実装する方法と、ASP.NET AJAXを使用する方法を紹介する予定です。 ここでは、荷物の大きさから[[ゆうパックの料金>http://www.post.japanpost.jp/fee/simulator/kokunai/parcel.html]]を調べるWebアプリケーションを作成します。DropDownListで荷物の大きさを選択すると、料金が表示されるようにします。料金の調査はサーバーで行い、その結果をクライアントが受け取り、表示します。 **Ajaxを使用しない方法 [#noajax] Ajaxを使用した方法と比較するために、まずはAjaxを一切使わない、今まで通りの方法で作成した例を示します。今までどおりの方法とは、ポストバックによってページ全体を更新する方法のことです。 この方法は非常に簡単で、DropDownListのAutoPostBackプロパティをTrueにして、SelectedIndexChangedイベントハンドラを追加し、このイベントハンドラで料金を計算して、結果を表示するだけです。以下にコードを示します。 #code(vbnet){{ <%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> Protected Sub PackageSizeList_SelectedIndexChanged( _ ByVal sender As Object, ByVal e As EventArgs) Dim ddl As DropDownList = CType(sender, DropDownList) If ddl.SelectedValue <> "0" Then Dim fee As Integer = _ Me.GetYoupackFee(Integer.Parse(ddl.SelectedValue)) ResultLabel.Text = String.Format("料金は {0}円", fee) Else ResultLabel.Text = "" End If End Sub Public Function GetYoupackFee(ByVal packSize As Integer) As Integer If packSize <= 60 Then Return 600 Else If packSize <= 80 Then Return 800 Else If packSize <= 100 Then Return 1000 Else If packSize <= 120 Then Return 1200 Else If packSize <= 140 Then Return 1400 Else If packSize <= 160 Then Return 1600 Else If packSize <= 170 Then Return 1700 Else Return -1 End If End Function </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>ゆうパック送料検索</title> </head> <body> <h1>ゆうパック送料検索</h1> <p>同一都道府県内への配達、重量30kgまで</p> <form id="form1" runat="server"> <div> <asp:Label ID="Label1" runat="server" Text="荷物の大きさ(縦・横・高さの合計): " AssociatedControlID="PackageSizeList"> </asp:Label> <asp:DropDownList ID="PackageSizeList" runat="server" AutoPostBack="True" OnSelectedIndexChanged="PackageSizeList_SelectedIndexChanged"> <asp:ListItem Value="0">(選択してください)</asp:ListItem> <asp:ListItem Value="60">60cmまで</asp:ListItem> <asp:ListItem Value="80">80cmまで</asp:ListItem> <asp:ListItem Value="100">100cmまで</asp:ListItem> <asp:ListItem Value="120">120cmまで</asp:ListItem> <asp:ListItem Value="140">140cmまで</asp:ListItem> <asp:ListItem Value="160">160cmまで</asp:ListItem> <asp:ListItem Value="170">170cmまで</asp:ListItem> </asp:DropDownList> <br /> <asp:Label ID="ResultLabel" runat="server"></asp:Label> </div> </form> </body> </html> }} #code(csharp){{ <%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> protected void PackageSizeList_SelectedIndexChanged( object sender, EventArgs e) { DropDownList ddl = (DropDownList)sender; if (ddl.SelectedValue != "0") { int fee = this.GetYoupackFee(int.Parse(ddl.SelectedValue)); ResultLabel.Text = string.Format("料金は {0}円", fee); } else { ResultLabel.Text = ""; } } public int GetYoupackFee(int packSize) { if (packSize <= 60) return 600; else if (packSize <= 80) return 800; else if (packSize <= 100) return 1000; else if (packSize <= 120) return 1200; else if (packSize <= 140) return 1400; else if (packSize <= 160) return 1600; else if (packSize <= 170) return 1700; else return -1; } </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>ゆうパック送料検索</title> </head> <body> <h1>ゆうパック送料検索</h1> <p>同一都道府県内への配達、重量30kgまで</p> <form id="form1" runat="server"> <div> <asp:Label ID="Label1" runat="server" Text="荷物の大きさ(縦・横・高さの合計): " AssociatedControlID="PackageSizeList"> </asp:Label> <asp:DropDownList ID="PackageSizeList" runat="server" AutoPostBack="True" OnSelectedIndexChanged="PackageSizeList_SelectedIndexChanged"> <asp:ListItem Value="0">(選択してください)</asp:ListItem> <asp:ListItem Value="60">60cmまで</asp:ListItem> <asp:ListItem Value="80">80cmまで</asp:ListItem> <asp:ListItem Value="100">100cmまで</asp:ListItem> <asp:ListItem Value="120">120cmまで</asp:ListItem> <asp:ListItem Value="140">140cmまで</asp:ListItem> <asp:ListItem Value="160">160cmまで</asp:ListItem> <asp:ListItem Value="170">170cmまで</asp:ListItem> </asp:DropDownList> <br /> <asp:Label ID="ResultLabel" runat="server"></asp:Label> </div> </form> </body> </html> }} ゆうパックの計算は、GetYoupackFeeメソッドで行っています。このメソッドは、今後も使用していきます。 **.NETの機能を使用せずに、Ajaxを使用する方法 [#pbedf191] Ajaxでは、上記の例のようにサーバーにポストバックしてページ全体を更新するのではなく、JavaScriptのようなクライアントスクリプトがサーバーと非同期通信を行い、動的にページの一部を更新します。 ここでは、Ajaxを使って、上の例と同じ事を行ってみましょう。ここで紹介する方法は、Webサービス以外は、.NET Frameworkの機能を一切使用しておらず、必要なJavaScriptのコードは全て自分で記述します。今後このメルマで、JavaScriptの知識をあまり必要としない、より簡単な方法を紹介する予定ですが、それらの方法で自動的に作成されるJavaScriptのコードも、基本的には、ここで紹介するコードと同様のことを行っているはずです。 まず、ゆうパックの料金を取得するためのWebサービスを作成します。Webサービスの作り方は前々号(第76号)で説明しましたので、ここでは説明しません。ここでは、以下のようなコードのWebサービスを"WebService.asmx"というファイル名で作成します。GetYoupackFeeメソッドの内容は、先ほどのものと同じです。 #code(vbnet){{ <%@ WebService Language="VB" Class="WebService" %> Imports System.Web Imports System.Web.Services Imports System.Web.Services.Protocols <WebService(Namespace := "http://tempuri.org/")> _ <WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _ Public Class WebService Inherits System.Web.Services.WebService <WebMethod()> _ Public Function GetYoupackFee(ByVal packSize As Integer) As Integer If packSize <= 60 Then Return 600 ElseIf packSize <= 80 Then Return 800 ElseIf packSize <= 100 Then Return 1000 ElseIf packSize <= 120 Then Return 1200 ElseIf packSize <= 140 Then Return 1400 ElseIf packSize <= 160 Then Return 1600 ElseIf packSize <= 170 Then Return 1700 Else Return -1 End If End Function End Class }} #code(csharp){{ <%@ WebService Language="C#" Class="WebService" %> using System; using System.Web; using System.Web.Services; using System.Web.Services.Protocols; [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] public class WebService : System.Web.Services.WebService { [WebMethod] public int GetYoupackFee(int packSize) { if (packSize <= 60) return 600; else if (packSize <= 80) return 800; else if (packSize <= 100) return 1000; else if (packSize <= 120) return 1200; else if (packSize <= 140) return 1400; else if (packSize <= 160) return 1600; else if (packSize <= 170) return 1700; else return -1; } } }} また、Web.configを以下のように書き換えて、WebサービスにHTTP GETでアクセスできるようにします。詳しくは、前々号をご覧ください。 #pre{{ <configuration> <system.web> <webServices> <protocols> <add name="HttpPost"/> <add name="HttpGet"/> </protocols> </webServices> </system.web> </configuration> }} 次に、メインとなるページを作成します。.NETの機能は一切使いませんので、「Ajaxを使用しない方法」と比べ、.NETのコードは全て削除し、HTMLの部分だけを使用することにします(ただ、DropDownListのAutoPostBackプロパティはFalseに戻します)。 また、JavaScriptの記述は別のファイル"ajax.js"で行いますので、<script>タグを追加して、その設定をしています。 補足:ここでは前のコードと比較する意味であえてASPXファイルとし、LabelやDropDownListコントロールを使っていますが、その必要はありません(むしろ無駄です)。普通のHTMLに、"PackageSizeList"というIDの<select>タグと、"ResultLabel"というIDの<span>タグがあれば十分です。 #code(vbnet){{ <%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>ゆうパック送料検索</title> <script type="text/javascript" src="ajax.js"></script> </head> <body> <h1>ゆうパック送料検索</h1> <p>同一都道府県内への配達、重量30kgまで</p> <form id="form1" runat="server"> <div> <asp:Label ID="Label1" runat="server" Text="荷物の大きさ(縦・横・高さの合計): " AssociatedControlID="PackageSizeList"> </asp:Label> <asp:DropDownList ID="PackageSizeList" runat="server"> <asp:ListItem Value="0">(選択してください)</asp:ListItem> <asp:ListItem Value="60">60cmまで</asp:ListItem> <asp:ListItem Value="80">80cmまで</asp:ListItem> <asp:ListItem Value="100">100cmまで</asp:ListItem> <asp:ListItem Value="120">120cmまで</asp:ListItem> <asp:ListItem Value="140">140cmまで</asp:ListItem> <asp:ListItem Value="160">160cmまで</asp:ListItem> <asp:ListItem Value="170">170cmまで</asp:ListItem> </asp:DropDownList> <br /> <asp:Label ID="ResultLabel" runat="server"></asp:Label> </div> </form> </body> </html> }} #code(csharp){{ <%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>ゆうパック送料検索</title> <script type="text/javascript" src="ajax.js"></script> </head> <body> <h1>ゆうパック送料検索</h1> <p>同一都道府県内への配達、重量30kgまで</p> <form id="form1" runat="server"> <div> <asp:Label ID="Label1" runat="server" Text="荷物の大きさ(縦・横・高さの合計): " AssociatedControlID="PackageSizeList"> </asp:Label> <asp:DropDownList ID="PackageSizeList" runat="server"> <asp:ListItem Value="0">(選択してください)</asp:ListItem> <asp:ListItem Value="60">60cmまで</asp:ListItem> <asp:ListItem Value="80">80cmまで</asp:ListItem> <asp:ListItem Value="100">100cmまで</asp:ListItem> <asp:ListItem Value="120">120cmまで</asp:ListItem> <asp:ListItem Value="140">140cmまで</asp:ListItem> <asp:ListItem Value="160">160cmまで</asp:ListItem> <asp:ListItem Value="170">170cmまで</asp:ListItem> </asp:DropDownList> <br /> <asp:Label ID="ResultLabel" runat="server"></asp:Label> </div> </form> </body> </html> }} 一番肝心の部分である、Webサービスにアクセスして料金を取得し、ページにその結果を表示する作業は、JavaScriptで行います。Webサービスと非同期で通信するには、XMLHttpRequestを使用します。また、Webサービスが返したXMLを解析するには、XMLDocumentオブジェクトを取得し、利用します。詳しくは、「[[AJAX:Getting Started>http://developer.mozilla.org/ja/docs/AJAX:Getting_Started]]」等を参考にしてください。 ここでは、以下のようなJavaScriptのコードを"ajax.js"に記述します。makeRequest関数などは、「[[AJAX:Getting Started>http://developer.mozilla.org/ja/docs/AJAX:Getting_Started]]」で紹介されているコードをほぼそのまま利用させていただきました。 #code(javascript){{ var msgElement, listElement; //onloadイベントハンドラを追加 if (window.addEventListener) { window.addEventListener("load", onLoad, false); } else if (window.attachEvent) { window.attachEvent("onload", onLoad); } else { window.onload = onLoad; } //onloadイベントハンドラ function onLoad() { msgElement = document.getElementById("ResultLabel"); listElement = document.getElementById("PackageSizeList"); if (window.addEventListener) { listElement.addEventListener("change", onChange, false); } else if (window.attachEvent) { listElement.attachEvent("onchange", onChange); } else { listElement.onchange = onChange; } } //リストのonchangeイベントハンドラ function onChange() { if (listElement.value == "0") { msgElement.innerHTML = ""; return; } msgElement.innerHTML = "読み込み中..."; //Webサービスにアクセスする var uri = "WebService.asmx/GetYoupackFee?packSize=" + listElement.value; if (!makeRequest(uri)) { msgElement.innerHTML = "XMLHTTPインスタンスの作成に失敗しました。"; } } //XMLHttpRequestオブジェクト生成 function makeRequest(url) { var http_request = false; if (window.XMLHttpRequest) { // Mozilla, Safari,... http_request = new XMLHttpRequest(); if (http_request.overrideMimeType) { http_request.overrideMimeType('text/xml'); } } else if (window.ActiveXObject) { // IE try { http_request = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { http_request = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { } } } if (!http_request) { return false; } http_request.onreadystatechange = function() { alertContents(http_request); };; http_request.open('GET', url, true); http_request.send(null); return true; } function alertContents(http_request) { if (http_request.readyState == 4) { var ret; //正しく受信できたかしらべる if (http_request.status == 200) { //XMLを解析する var doc = http_request.responseXML; var node = doc.getElementsByTagName('int').item(0); var fee = node.firstChild.nodeValue; ret = "料金は " + fee + "円"; } else { ret = "正しく取得できませんでした。"; } //結果を表示 msgElement.innerHTML = ret; } } }} 補足:上記の例では、onloadやonchangeイベントハンドラの追加でかなり面倒なことをしていますが、window.onloadやonchange属性を使用して、もっと簡単にすることもできます。詳しくは、「[[方法 : ASP.NET Web サーバー コントロールにクライアント スクリプト イベントを追加する>http://msdn2.microsoft.com/ja-jp/library/7ytf5t7k(VS.80).aspx]]」などをご覧ください。 当然のことですが、このようにAjaxでは、JavaScriptの知識がかなり必要になります。しかし、.NET Framework 2.0以降では、より簡単な方法も用意されています。次回からは、それらを紹介していく予定です。 **参考 [#z57fa47e] -[[An Introduction to AJAX Techniques and Frameworks for ASP.NET - The Code Project>http://www.codeproject.com/Ajax/IntroAjaxASPNET.asp]] -[[クライアント スクリプトを使用する ASP.NET Web ページのプログラミング>http://msdn2.microsoft.com/ja-jp/library/50b7y38h(VS.80).aspx]] //これより下は編集しないでください #pageinfo([[:Category/.NET]] [[:Category/ASP.NET]],2007-10-23 (火) 02:26:38,DOBON!,2007-11-18 (日) 23:52:49,DOBON!) |