- 追加された行はこの色です。
- 削除された行はこの色です。
#title(ASP.NETでAjaxを使用したWebアプリケーションを作成する 1)
#navi(.NETプログラミング研究)
#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を使用する方法 [#nodotnet]
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]]
**コメント [#q1984f69]
#comment
//これより下は編集しないでください
#pageinfo([[:Category/.NET]] [[:Category/ASP.NET]],2007-10-23 (火) 02:26:38,DOBON!,2008-07-04 (金) 02:29:58,DOBON!)