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;
 
//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 サーバー コントロールにクライアント スクリプト イベントを追加する」などをご覧ください。

当然のことですが、このようにAjaxでは、JavaScriptの知識がかなり必要になります。しかし、.NET Framework 2.0以降では、より簡単な方法も用意されています。次回からは、それらを紹介していく予定です。

参考

コメント



ページ情報
[ トップ ]   [ 編集 | 凍結 | 差分 | バックアップ | 添付 | 複製 | 名前変更 | リロード ]   [ 新規 | 子ページ作成 | 一覧 | 単語検索 | 最終更新 | ヘルプ ]