.NETプログラミング研究 RSSを登録する

Microsoft .NET Frameworkプログラミング(主にVisual Basic .NET、C#)で役に立つTipsやFAQなどをサンプル満載で紹介します。「DOBON.NET」(http://dobon.net)発行。

最新号をメルマガでお届けします    
登録 解除

規約に同意して

登録した方には、まぐまぐの公式メルマガ(無料)をお届けします。
2008/07/14

.NETプログラミング研究 第84号

この記事を取り寄せる

┏第84号━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃         .NETプログラミング研究         ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

──<メニュー>───────────────────────
■.NET Tips
・Microsoft ASP.NET AJAXを使う5
 -WebサービスのメソッドをJavaScriptから呼び出す
───────────────────────────────

[URL].NETプログラミング研究 第84号 Web版
http://wiki.dobon.net/index.php?.NET%A5%D7%A5%ED%A5%B0%A5%E9%A5%DF%A5%F3%A5%B0%B8%A6%B5%E6%2F84

───────────────────────────────
■.NET Tips
───────────────────────────────
●Microsoft ASP.NET AJAXを使う5

★WebサービスのメソッドをJavaScriptから呼び出す

これまではUpdatePanelコントロールを中心にASP.NET AJAXを説明して
きました。それらの方法では、Webサービスを自分で作成する必要があ
りませんでした。

ここでもう一度原点に返って、自分で作成したWebサービスを利用して
Ajaxを実現する方法について説明します。ASP.NET AJAXを利用すれば、
これも驚くほど簡単です。

ここでは、第78号で紹介した「.NETの機能を使用せずに、Ajaxを使用す
る方法」と全く同じ事を行うアプリケーションをASP.NET AJAXを利用し
て作成します。

☆Webサービス

まずは、Webサービスの作成です。「.NETの機能を使用せずに、Ajaxを
使用する方法」で紹介したWebサービスのクラスに、新たに
ScriptServiceAttribute属性を適用します。それ以外は、変更なしです。
ファイル名は、"WebService.asmx"とします。

[URL]ScriptServiceAttribute属性
http://search.microsoft.com/results.aspx?q=ScriptServiceAttribute+%e3%82%af%e3%83%a9%e3%82%b9&l=2

‥‥▽VB.NET ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
<%@ 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)> _
<System.Web.Script.Services.ScriptService> _
Public Class WebService
    Inherits System.Web.Services.WebService 
    
    <WebMethod()> _
    Public Function GetYoupackFee(ByVal packSize As Integer) As Integer
        '(省略)
    End Function
End Class
‥‥△VB.NET ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥

‥‥▽C# ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
<%@ 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)]
[System.Web.Script.Services.ScriptService]
public class WebService  : System.Web.Services.WebService
{
    [WebMethod]
    public int GetYoupackFee(int packSize)
    {
        //(省略)
    }
}
‥‥△C# ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥

「.NETの機能を使用せずに、Ajaxを使用する方法」では、Web.configを
書き換えてWebサービスにHTTP GETでアクセスできるようにしましたが、
その必要はありません。

ただし、Web.configに以下のような設定を追加して、
ScriptHandlerFactory HTTPハンドラを登録する必要があります。もし
Visual Studio 2008でプロジェクトを作成したか、Visual Studio 2005
で「ASP.NET AJAX-Enabled Web Site」テンプレートを使用してプロジ
ェクトを作成したのであれば、この設定はすでにされていますので、気
にする必要はありません。

<system.web>
  <httpHandlers>
    <remove verb="*" path="*.asmx"/>
    <add verb="*" path="*.asmx" type="System.Web.Script.Services.ScriptHandlerFactory" validate="false"/>
  </httpHandlers>
<system.web>

☆ページ

次に、Webサービスを呼び出すページを作成します。前回との違いは、
ScriptManagerコントロールを配置する点です。

[URL]ScriptManagerコントロール
http://search.microsoft.com/results.aspx?q=ScriptManager+%e3%82%af%e3%83%a9%e3%82%b9&l=2

そして、ScriptManagerのServicesプロパティに先ほど作成したWebサー
ビスを追加します。また、ScriptManagerのScriptsプロパティに
JavaScriptファイルを追加します。

[URL]Servicesプロパティ
http://search.microsoft.com/results.aspx?q=ScriptManager.Services+%e3%83%97%e3%83%ad%e3%83%91%e3%83%86%e3%82%a3&l=2

‥‥▽VB.NET ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
<%@ 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>
</head>
<body>
    <h1>ゆうパック送料検索</h1>
    <p>同一都道府県内への配達、重量30kgまで</p>
    <form id="form1" runat="server">
    <div>
        <asp:ScriptManager ID="ScriptManager1" runat="server">
            <Scripts>
                <asp:ScriptReference Path="ajax.js" />
            </Scripts>
            <Services>
                <asp:ServiceReference Path="WebService.asmx" />
            </Services>
        </asp:ScriptManager>
        
        <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>
‥‥△VB.NET ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥

‥‥▽C# ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
<%@ 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>
</head>
<body>
    <h1>ゆうパック送料検索</h1>
    <p>同一都道府県内への配達、重量30kgまで</p>
    <form id="form1" runat="server">
    <div>
        <asp:ScriptManager ID="ScriptManager1" runat="server">
            <Scripts>
                <asp:ScriptReference Path="ajax.js" />
            </Scripts>
            <Services>
                <asp:ServiceReference Path="WebService.asmx" />
            </Services>
        </asp:ScriptManager>
        
        <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>
‥‥△C# ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥

☆ServiceReference.InlineScriptプロパティ

この例では、Servicesプロパティに追加するServiceReferenceオブジェ
クトにはPathプロパティの値しか指定しておらず、InlineScriptプロパ
ティはデフォルトのfalseのままとしました。

[URL]ServiceReferenceオブジェクト
http://search.microsoft.com/results.aspx?q=ServiceReference+%e3%82%af%e3%83%a9%e3%82%b9&l=2

[URL]Pathプロパティ
http://search.microsoft.com/results.aspx?q=ServiceReference.Path+%e3%83%97%e3%83%ad%e3%83%91%e3%83%86%e3%82%a3&l=2

[URL]InlineScriptプロパティ
http://search.microsoft.com/results.aspx?q=ServiceReference.InlineScript+%e3%83%97%e3%83%ad%e3%83%91%e3%83%86%e3%82%a3&l=2

InlineScriptプロパティがfalseのときは、後述するプロキシクラスを
作成するJavaScriptを外部ファイルとして(<javascript>タグのscr属
性に設定して)呼び出します。InlineScriptプロパティがtrueのときは、
ページ内にJavaScriptが埋め込まれます。また、InlineScriptプロパテ
ィがtrueのときは、Pathプロパティは相対パスである必要があります。

つまり、InlineScriptプロパティがfalseのときは、サーバーへの要求
数が増えますが、ブラウザのキャッシュ機能が使われる可能性があり、
trueのときは、ページのサイズが大きくなります。

☆JavaScript

最後に、Webサービスを呼び出すJavaScriptを作成します。前回とほぼ
同じ事を行っていますが、劇的にシンプルになることをご確認ください。

‥‥▽JavaScript ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
var msgElement, listElement;

Sys.Application.add_load(ApplicationLoad)

function ApplicationLoad(sender, args)
{
    msgElement = $get('ResultLabel');
    listElement = $get('PackageSizeList');
    //DropDownListのonchangeイベントハンドラを追加する
    $addHandler(listElement, 'change', onChange);
}

function onChange()
{
    if (listElement.value == "0")
    {
        msgElement.innerHTML = "";
        return;
    }
    
    msgElement.innerHTML = "読み込み中...";
 
    //Webサービスにアクセスする
    WebService.GetYoupackFee(listElement.value, OnSucceeded, OnFailed);
}

function OnSucceeded(result, userContext, methodName)
{
    msgElement.innerHTML = "料金は " + result + "円";
}

function OnFailed(error, userContext, methodName)
{
    if(error != null)
    {
        msgElement.innerHTML = "エラー: " + error.get_message();
    }
}

if (typeof(Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();
‥‥△JavaScript ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥

loadイベントハンドラでは、DropDownList"PackageSizeList"の
onchangeイベントハンドラを追加しています。前回はaddEventListener
を使うか、attachEventを使うかなどを調べていましたが、ASP.NET 
AJAXでは$addHandlerを使って一発でできます。

[URL]$addHandler
http://search.microsoft.com/results.aspx?q=Sys.UI.DomEvent+%e3%81%ae+%24addHandler+%e3%83%a1%e3%82%bd%e3%83%83%e3%83%89&l=2

☆プロキシクラス

onchangeイベントハンドラでWebサービスを呼び出しています。ご覧の
通り、まるでWebサービスのメソッドをJavaScriptから直接呼び出して
いるかのように、Webサービスにアクセスできます。この例ではWebサー
ビスのクラスに名前空間がありませんでしたが、名前空間がある場合は
名前空間も付けて呼び出す必要があります(例えば名前空間が「
MyNameSpace」であれば、「MyNameSpace.WebService.GetYoupackFee(..
.)」のように)。

なぜこれだけ簡単にWebサービスメソッドを呼び出せるかというと、ASP
.NET AJAXが自動的にプロキシクラスを作成してくれるからです。この
例では、WebServiceクラスがプロキシクラスです。プロキシクラスには
Webサービスメソッドを呼び出すためのメソッドが作成されており、メ
ソッドの名前は対応するWebサービスメソッドと同じです。

[URL]プロキシクラス
http://msdn.microsoft.com/ja-jp/library/bb310823.aspx

プロキシクラスのメソッドのパラメータには、まず対応するWebサービ
スメソッドのパラメータを渡します。上記の例ではWebサービスメソッ
ドのパラメータ数は1つだけですが、複数ある場合はその数だけ渡しま
す。

その次のパラメータには、Webサービスへの要求が成功したときに呼び
出されるコールバック関数を指定します。上の例では、OnSucceeded関
数がそれです。このパラメータは省略できます。

その次のパラメータには、失敗したときに呼び出されるコールバック関
数を指定します。上の例では、OnFailed関数がそれです。このパラメー
タも省略できます。

上の例では省略しましたが、さらに次のパラメータに、ユーザーコンテ
キストを指定できます。ここで指定したコンテキストは、成功/失敗コ
ールバック関数で取得できます。Webサービスメソッドがどこから呼び
出されたのかを区別したいときなどに有用です。

プロキシクラスのtimeoutプロパティに、タイムアウトの時間を設定す
ることもできます。

補足:成功コールバック関数、失敗コールバック関数、ユーザーコンテ
キストは、プロキシクラスのdefaultSucceededCallbackプロパティ、
defaultFailedCallbackプロパティ、defaultUserContextプロパティに
設定することもできます。

成功コールバック関数では、Webサービスメソッドが返した値(result
パラメータ)、ユーザーコンテキスト(userContextパラメータ)、呼
び出されたWebサービスメソッド名(methodNameパラメータ)を取得で
きます。

失敗コールバック関数では、エラー情報をerrorパラメータで取得でき
ます。これは、Sys.Net.WebServiceErrorオブジェクトです。例えばエ
ラーメッセージは、上記の例のように、messageプロパティで取得でき
ます。

☆Sys.Net.WebServiceProxyクラス

プロキシクラスは、Sys.Net.WebServiceProxyクラスから派生していま
す。クライアント側で呼び出すWebサービスのパスが直前まで分からな
いとき(ScriptManagerのServicesに登録されていないWebサービスを呼
び出すとき)には、WebServiceProxyクラスを直接使ってWebサービスに
アクセスすることができます。

上記の例を改造して、ScriptManagerのServicesにWebサービスが登録さ
れていないときに、WebService.GetYoupackFeeメソッドを呼び出すスク
リプト(メソッドを呼び出す部分のみ)を以下に示します。

‥‥▽JavaScript ここから▽‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
Sys.Net.WebServiceProxy.invoke('WebService.asmx',
    'GetYoupackFee',
    false,
    {'packSize':listElement.value},
    OnSucceeded,
    OnFailed,
    null,
    60000);
‥‥△JavaScript ここまで△‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥

このようにWebServiceProxy.invokeメソッドでWebサービスメソッドを
呼び出せます。3番目のパラメータは、Webサービスへの要求をGETで行
うかを指定します。falseの場合はPOSTとなります。4番目のパラメータ
には、Webサービスに渡すパラメータを連想配列で指定します。7番目の
パラメータはユーザーコンテキストです。8番目のパラメータはタイム
アウト時間(単位はミリ秒)です。

★参考

[URL]ASP.NET AJAX での Web サービス
http://search.microsoft.com/results.aspx?q=ASP.NET+AJAX+%e3%81%a7%e3%81%ae+Web+%e3%82%b5%e3%83%bc%e3%83%93%e3%82%b9&l=2

===============================
■ここで示したコードの多くはまずC#で書き、それを「C# to VB.NET 
 Translator」でVB.NETのコードに変換し、修正を加えたものです。

[URL]C# to VB.NET Translator
http://authors.aspalliance.com/aldotnet/examples/translate.aspx

■このマガジンの購読、購読中止、バックナンバー、説明に関しては
 次のページをご覧ください。
 http://www.mag2.com/m/0000104516.htm

■発行人・編集人:どぼん!
 http://dobon.net

■ご質問等はメールではなく、掲示板へお願いいたします。
 http://dobon.net/vb/bbs.html

■メールは下記URLのフォームメールから送信してください。
 http://dobon.net/mail.html

Copyright (c) DOBON!  All rights reserved.
===============================

この記事を取り寄せる
最新号をメルマガでお届け
登録 解除

規約に同意して

登録した方には、まぐまぐの公式メルマガ(無料)をお届けします。

最近の記事

上へ戻る