AJAXが主流になってきている昨今である。サーバ側のコードだってJavaScriptから簡単に呼び出せるようにしてくれたのがMicrosoftのAJAXだ。利点はPostBackをせずに、つまり、ページのリフレッシュをせずに動的にHTMLの要素を表示し、ユーザの使い勝手をよくしようとするものだ。この記事ではウェブサービスから返されたHTMLの文字列をJavaScriptで読み込み、それを動的に表示する方法を簡単な例で紹介する。
まずはASP .NETのプロジェクトに.asmxのファイルを追加する。ウェブサービスだからといって別途ウェブサービスのプロジェクトを用意する必要はない。この例ではSimpleService.asmxと名前をつける。そして下のようにコードを書く。
1: Imports System.Web.Services
2: Imports System.Web.Services.Protocols
3: Imports System.ComponentModel
4: Imports System.Web.UI.HtmlControls
5: Imports System.IO
6: Imports System.Text
7:
8: ' To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
9: ' <System.Web.Script.Services.ScriptService()> _
10: <System.Web.Services.WebService(Namespace:="http://tempuri.org/")> _
11: <System.Web.Services.WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
12: <ToolboxItem(False)> _
13: <System.Web.Script.Services.ScriptService()> _
14: Public Class SimpleService
15: Inherits System.Web.Services.WebService
16:
17: <WebMethod()> _
18: Public Function GetHtml() As String
19: ' まずはクライアント側に返したいHTMLをSystem.Web.UI.HtmlControlsにあるクラス群を使って作成する。
20: Dim cell1 As New HtmlTableCell()
21: cell1.InnerText = "Hello Cell1"
22:
23: Dim row1 As New HtmlTableRow()
24: row1.Cells.Add(cell1)
25:
26: Dim table As New HtmlTable()
27: table.Rows.Add(row1)
28: table.Border = 1
29:
30: ' ここからHTMLコントロールを文字列に変えるプロセス。
31: Dim sb As New StringBuilder()
32: Dim sw As New StringWriter(sb)
33: Dim htmlWriter As New HtmlTextWriter(sw)
34:
35: table.RenderControl(htmlWriter)
36:
37: Return sb.ToString()
38:
39: End Function
40:
41: End Class
上のコードをもうちょっと解説する。13行目のSimpleServiceクラスに対するAttributeは追加してやらなければいけません。これはJavaScriptから呼び出すことを可能にしますよというAttributeだ。そしてGetHtmlというFunctionを作成しStringを返すようにしてやる。もちろんWebMethodのAttributeをつけてやるのも忘れないようにする。そしてTableを作成してHtmlTableのオブジェクトをRenderControlというメソッドを実行するとStringBuilderにそのHTMLが入っているのでそれを返してやるだけだ。これでウェブサービスの準備は完了だ。
次にクライアント側だ。ASP.NETのプロジェクトを作成するとDefalt.aspxがついてくるのでそれを使う。
ASP.NETでAJAXを使うには必ずそのページにScriptManagerを追加してやらなければならない。これはformタグ内に入れてやるといい。そのScriptManager内にはServicesというコレクションが存在し、そこに先ほど書いたSimpleService.asmxへの参照を追加してやる。
<asp:ScriptManager runat="server" ID="ScriptManager1">
<Services>
<asp:ServiceReference Path="~/SimpleService.asmx" />
</Services>
</asp:ScriptManager>
これでウェブサービスを直接JavaScriptから呼び出せる。
Default.aspxにHTMLボタンを貼り付けてそのonclickのイベントハンドラーで次のようなJavaScriptを書く。
function Button1_onclick() { AjaxTest.SimpleService.GetHtml(OnComplete, OnTimeOut, OnError); return true; }
実際にコードをVS2008上で書いてみるとJavaScriptのインテリセンスが表示されるので便利だ。通常はJavaScriptからウェブサービスへのコールは非同期で行われるので上のようなコードになる。それではOnCompleteを見てみよう。
function OnComplete(arg) { alert(arg); var divLayer = document.getElementById("divHtmlPlaceHolder"); divLayer.innerHTML = arg; }
ここではウェブサービスから受け取ったHTMLを一度alertで表示させて既存のdivタグ内(divHtmlPlaceHolder)に入れてやるのだ。OnErrorとOnTimeOutも下に貼り付けておこう。
function OnTimeOut(arg) { alert("Call timed out"); } function OnError(arg) { alert("Error happened"); }
これで簡単にサーバ側のコードがJavaScript側から呼び出せる。
更新:Fiddler2でHTMLトラフィックを見てみました。Responseはこんな感じです。XMLを使わずコンパクトでいいんじゃないでしょうか。
HTTP/1.1 200 OK
Cache-Control: private, max-age=0
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/7.0
X-AspNet-Version: 2.0.50727
X-Powered-By: ASP.NET
Date: Sun, 27 Jul 2008 23:47:37 GMT
Content-Length: 153
{"d":"\u003ctable border=\"1\"\u003e\r\n\t\u003ctr\u003e\r\n\t\t\u003ctd\u003eHello Cell1\u003c/td\u003e\r\n\t\u003c/tr\u003e\r\n\u003c/table\u003e\r\n"}
コメント書き込み