ASP.NETでAjaxを使用したWebアプリケーションを作成する 1 †
「.NETプログラミング研究」の第76号で予告したとおり(かなり間が開いてしまいましたが)、今回から何回かに分けてASP.NETでAjaxを使ったWebアプリケーションを作成する方法を紹介します。今回は、.NETの機能を全く使用しない方法を紹介します。今後は、.NET Framework 2.0から追加されたICallbackEventHandlerインターフェイスを実装する方法と、ASP.NET AJAXを使用する方法を紹介する予定です。
ここでは、荷物の大きさからゆうパックの料金を調べるWebアプリケーションを作成します。DropDownListで荷物の大きさを選択すると、料金が表示されるようにします。料金の調査はサーバーで行い、その結果をクライアントが受け取り、表示します。
Ajaxを使用しない方法 †
Ajaxを使用した方法と比較するために、まずはAjaxを一切使わない、今まで通りの方法で作成した例を示します。今までどおりの方法とは、ポストバックによってページ全体を更新する方法のことです。
この方法は非常に簡単で、DropDownListのAutoPostBackプロパティをTrueにして、SelectedIndexChangedイベントハンドラを追加し、このイベントハンドラで料金を計算して、結果を表示するだけです。以下にコードを示します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
| | <%@ 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>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
| | <%@ 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を使用する方法 †
Ajaxでは、上記の例のようにサーバーにポストバックしてページ全体を更新するのではなく、JavaScriptのようなクライアントスクリプトがサーバーと非同期通信を行い、動的にページの一部を更新します。
ここでは、Ajaxを使って、上の例と同じ事を行ってみましょう。ここで紹介する方法は、Webサービス以外は、.NET Frameworkの機能を一切使用しておらず、必要なJavaScriptのコードは全て自分で記述します。今後このメルマで、JavaScriptの知識をあまり必要としない、より簡単な方法を紹介する予定ですが、それらの方法で自動的に作成されるJavaScriptのコードも、基本的には、ここで紹介するコードと同様のことを行っているはずです。
まず、ゆうパックの料金を取得するためのWebサービスを作成します。Webサービスの作り方は前々号(第76号)で説明しましたので、ここでは説明しません。ここでは、以下のようなコードのWebサービスを"WebService.asmx"というファイル名で作成します。GetYoupackFeeメソッドの内容は、先ほどのものと同じです。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
| | <%@ 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
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
| | <%@ 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でアクセスできるようにします。詳しくは、前々号をご覧ください。
<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>タグがあれば十分です。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
| | <%@ 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>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
| | <%@ 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」等を参考にしてください。
ここでは、以下のようなJavaScriptのコードを"ajax.js"に記述します。makeRequest関数などは、「AJAX:Getting Started」で紹介されているコードをほぼそのまま利用させていただきました。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
| | var msgElement, listElement;
if (window.addEventListener)
{
window.addEventListener("load", onLoad, false);
}
else if (window.attachEvent)
{
window.attachEvent("onload", onLoad);
}
else
{
window.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;
}
}
function onChange()
{
if (listElement.value == "0")
{
msgElement.innerHTML = "";
return;
}
msgElement.innerHTML = "読み込み中...";
var uri = "WebService.asmx/GetYoupackFee?packSize=" + listElement.value;
if (!makeRequest(uri))
{
msgElement.innerHTML = "XMLHTTPインスタンスの作成に失敗しました。";
}
}
function makeRequest(url)
{
var http_request = false;
if (window.XMLHttpRequest)
{
http_request = new XMLHttpRequest();
if (http_request.overrideMimeType)
{
http_request.overrideMimeType('text/xml');
}
}
else if (window.ActiveXObject)
{
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)
{
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 サーバー コントロールにクライアント スクリプト イベントを追加する」などをご覧ください。
当然のことですが、このようにAjaxでは、JavaScriptの知識がかなり必要になります。しかし、.NET Framework 2.0以降では、より簡単な方法も用意されています。次回からは、それらを紹介していく予定です。
参考 †
コメント †