2.7 ASP.NET AJAX Hello World 示例程序
Hello World 已经成为所有语言教科书中的必备示例程序,本书也不能免于俗套。在本章的最后,
我们还是通过一个最简单的ASP.NET AJAX Hello World 应用程序来迈出这勇敢的第一步。
2.7.1 示例程序介绍
该程序的界面上有一个文本框和一个按钮,如图2-16 所示。用户在文本框中输入自己的名字之
后点击这个按钮,ASP.NET AJAX 将异步调用位于服务器端的一个Web Service 。在得到一个问
候字符串后,将其显示在页面中,如图2-17 所示。需要注意的是,显示问候字符串时页面并不
是完全重新加载,而只是进行局部更新,避免了浏览器重绘时的闪烁,也就是所谓的“Ajax” 方
式。
图2-16 ASP.NET AJAX Hello World 程序界面
图2-17 服务器发给Dflying 的问候
2.7.2 设计页面的HTML 部分
要实现这个简单的Hello World 程序,首先建立一个ASP.NET AJAX Web Site ,并在其中新建名
为ASPNETAJAXHelloWorld.aspx 的ASP.NET 页面。在该页面中,添加如下的HTML 标记:
<label for="tbName">Your Name:</label><input id="tbName" type="text" />
<input id="btnSayHello" type="button" value="Say Hello From Server!" />
<div id="lbMessage"></div>
可以看到,其中定义了一个作为文本框显示的<input>,id 为tbName,用来让用户输入名字;一
个id 为btnSayHello 的作为按钮显示的<input>,用来触发对服务器的异步调用;一个空的<div>,
id 为lbMessage ,服务器端返回的结果将显示在这里。
页面中包含了一些简单的CSS ,代码如下:
*
{
font-family: Tahoma;
font-size: 0.96em;
}
input
{
border: 1px solid #000;
}
这样,本程序中所有的界面部分元素就完成了。运行一下,应该可以看到如图2-16 所示的界面。
自然,此时该程序尚不能完成任何功能。
2.7.3 编写提供服务的Web Service
然后编写服务器端的Web Service 。在本ASP.NET AJAX Web Site 中创建一个Web Service ,命名
为HelloWorldService.asmx 。在其中声明一个Web Method ,该Web Service 的代码如下,注意其
中粗体部分:
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
[WebService(Namespace = "http://www.dflying.net/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService()]
public class HelloWorldService : System.Web.Services.WebService
{
[WebMethod]
public string GetHelloWorldString(string name)
{
return string.Format("Welcome to ASP.NET AJAX world, {0}!. Now it is {1}.",
name,DateTime.Now);
}
}
可以看到,我们为该Web Service 类应用了[System.Web.Script.Services.ScriptService()] 属性,这
个属性是让ASP.NET AJAX 能够从客户端访问到该Web Service 所必需的。该Web Method 的名
称为GetHelloWorldString() ,它接受一个string 作为参数并将同样返回一个string 。其实现非常
简单,即构造并返回一个包含用户输入的名字和当前服务器的时间的字符串。
编辑完成该Web Service 之后,我们可以先在浏览器中运行并测试一下——在开发过程中随时对
现有代码进行阶段性测试是一个非常好的习惯,有助于尽早发现潜在的错误。若一切顺利,你
将看到如图2-18 所示的Web Service 测试页面。
图2-18 Web Service 测试页面
点击GetHelloWorldString 链接,导航至GetHelloWorldString() 方法的测试页面,并输入一个用户
名(见图2-19)。
点击Invoke 按钮,一切顺利的话,你将看到如图2-20 所示的GetHelloWorldString() 方法的返回
值(其中时间部分可能有所不同)。
图2-19 GetHelloWorldString() 方法的测试页面
图2-20 调用GetHelloWorldString() 方法
这样,服务器端的准备即宣告完成。接下来让我们生成并在页面中引用这个Web Method 的客
户端代理,以便于稍后在客户端JavaScript 中对其进行调用。
2.7.4 使用ScriptManager 控件在页面上添加Web Service 的客户端引用
切换回ASPNETAJAXHelloWorld.aspx 页面的设计器,从Toolbox 中拖入一个ASP.NET AJAX
ScriptManager 控件。这时ASPNETAJAXHelloWorld.aspx 页面的设计器应该如图2-21 所示。
ScriptManager 控件是ASP.NET AJAX 的核心,用来将ASP.NET AJAX 框架所需要的JavaScript
文件、自定义的ASP.NET AJAX 客户端组件以及该页面将要调用的Web Service 的客户端代理
发送到客户端。关于ScriptManager 控件,将在第3 章中详细介绍。
图2-21 添加了ScriptManager 控件的ASP.NET 页面
因为这个程序中将用到前面创建的文件名为HelloWorldService.asmx 的Web Service ,所以我们
需要在ScriptManager 控件中添加其引用,这样ScriptManager 控件才可以自动生成它的客户端
JavaScript 代理并发送至浏览器。
选中ScriptManager 控件,然后在Properties 工具窗口中点击Services 右面的按钮,如图2-22 所
示。
图2-22 Properties 工具窗口中的ScriptManager 控件
在弹出的对话框中点击Add 按钮添加一个新的Service ,并指定其Path 为HelloWorldService.
asmx ,添加后的界面将如图2-23 所示。
图2-23 为ScriptManager 控件添加Service 引用
点击OK 按钮之后,HelloWorldService.asmx 的引用就被添加到了ScriptManager 中。由于程序
中还需要使用一些定义在“Futures”脚本中的客户端控件,所以接下来我们还要在ScriptManager
中添加相应的“Futures”脚本引用。
选中ScriptManager 控件,然后在Properties 工具窗口中点击Scripts 右面的按钮,将弹出
ScriptReference Collection Editor 对话框。点击Add 按钮添加一个新的Script,并指定其Assembly
为Microsoft.Web.Preview ,Name 为PreviewScript.js ,这样做即表示我们要把内嵌在
Microsoft.Web.Preview.dll 程序集中的名为PreviewScript.js 的脚本资源引入到页面中。添加后的
界面将如图2-24 所示。
图2-24 为ScriptManager 控件添加Script 引用
点击OK 按钮之后,这个“Futures” 脚本的引用就被添加到了ScriptManager 中。这时若切换至页
面的源文件视图,可以看到Visual Studio 自动为我们生成了如下ScriptManager 控件的代码:
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Scripts>
<asp:ScriptReference Name="PreviewScript.js"
Assembly="Microsoft.Web.Preview" />
</Scripts>
<Services>
<asp:ServiceReference Path="HelloWorldService.asmx" />
</Services>
</asp:ScriptManager>
2.7.5 用JavaScript 让程序运转起来
最后一步,让客户端以异步的方式直接调用该Web Service 中的GetHelloWorldString() 方法以取
得客户端所需的数据。用ASP.NET AJAX XML 脚本的方式可能较难理解,所以在这个示例程序
中我们选择用JavaScript 的方式。
首先,在页面的<head> 标签中插入一个<script> 标签,并在其中定义三个控件,分别代表让用户
输入名字的文本框、用来触发对服务器进行请求的按钮以及用来显示服务器端返回结果的标签:
var g_tbName = null;
var g_btnSayHello = null;
var g_lbMessage = null;
然后定义一个pageLoad() 方法。类似于ASP.NET 中服务器端的Page_Load() 方法,该pageLoad()
方法将在ASP.NET AJAX 客户端框架初始化之后自动被调用,程序可以在其中进行一些必要的
初始化操作。这里我们在该方法中初始化上面的三个ASP.NET AJAX 客户端控件:
function pageLoad()
{
g_tbName = new Sys.Preview.UI.TextBox($get('tbName'));
g_tbName.initialize();
g_btnSayHello = new Sys.Preview.UI.Button($get('btnSayHello'));
g_btnSayHello.add_click(getServerHelloString);
g_btnSayHello.initialize();
g_lbMessage = new Sys.Preview.UI.Label($get('lbMessage'));
g_lbMessage.initialize();
}
在pageLoad() 方法的第一行,我们看到了一个奇怪的函数——$get() 。该函数是ASP.NET AJAX
提供的对JavaScript 函数document.getElementById() 的简写形式,用来通过DOM 元素的id 来找
到这个DOM 元素。然后,将这个DOM 元素的引用传递给Sys.Preview.UI.TextBox,即ASP.NET
AJAX 客户端TextBox 控件的构造函数,表示该TextBox 控件将作为这个DOM 元素在ASP.NET
AJAX 客户端框架中的封装。也就是说,这个TextBox 控件实际上以面向对象的方法封装了真
正的DOM 元素的各种属性/操作。最后,将返回的客户端TextBox 控件的引用保存在tbName
中。关于ASP.NET AJAX 的客户端控件,将在第Ⅱ卷中详细介绍。
第二行中调用了该TextBox 控件的initialize() 方法,对其进行了初始化。
对于按钮和显示返回结果的标签,我们也采用了同样的方式进行初始化。但是需要注意的是下
面这一句:
g_btnSayHello.add_click(getServerHelloString);
该句代码为g_btnSayHello 按钮的click 事件添加了一个事件处理函数,名为getServer-
HelloString() 。getServerHelloString() 事件处理函数的代码如下:
function getServerHelloString()
{
HelloWorldService.GetHelloWorldString(g_tbName.get_text(), cb_getServerHello
String);
}
这个函数中只有一条语句,就是调用HelloWorldService.asmx 文件中GetHelloWorldString() 方法
的客户端代理。可以看到调用该方法的格式为[类名].[ 方法名],很让人兴奋,不是吗?居然如此
简单直观,和我们熟悉的C#代码结构完全一样!完全不用像第1 章中示例程序那样要书写那么
多的代码。
我们为该方法传入了两个参数:第一个是用户在文本框中的名字字符串,通过g_tbName.get_text()
得到,当它到达服务器端时,ASP.NET AJAX 会自动将其转化为.NET 框架中的String 对象;第
二个是该异步调用完成时的回调函数,我们将其指定为cb_getServerHelloString() 。关于ASP.NET
AJAX 中调用Web Service 的详细方法,将在第Ⅱ卷中详细介绍。
让我们再看一下cb_getServerHelloString() 回调函数的代码:
function cb_getServerHelloString(result)
{
g_lbMessage.set_text(result);
}
该函数同样非常简单明了。注意到该函数接受一个名为result 的参数,这是ASP.NET AJAX 框
架自动提供的,其中包含了这次异步调用的返回值。在本示例程序中,result 参数也就是
HelloWorldService.asmx 文件中GetHelloWorldString() 方法的返回值。在返回值发送至客户端之
后,ASP.NET AJAX 客户端框架同样将把它转换为JavaScript 中的字符串对象。然后在该函数中,
我们调用g_lbMessage.set_text(result) 方法,将服务器端返回的字符串设定给了g_lbMessage 并显
示出来。
ajaxHelloworld.aspx
//c# code
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="ajaxHelloworld.aspx.cs" Inherits="ajaxHelloworld" %>
<%@ Register Assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
Namespace="System.Web.UI" TagPrefix="asp" %>
<!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 runat="server">
<title>ajaxHelloworld</title>
<style type="text/css">
*
{
font-family: Tahoma;
font-size: 0.96em;
}
input
{
border: 1px solid #000;
}
</style>
<script type="text/javascript">
var g_tbName = null;
var g_btnSayHello = null;
var g_lbMessage = null;
function pageLoad()
{
g_tbName = new Sys.Preview.UI.TextBox($get('tbName'));
g_tbName.initialize();
g_btnSayHello = new Sys.Preview.UI.Button($get('btnSayHello'));
g_btnSayHello.add_click(getServerHelloString);
g_btnSayHello.initialize();
g_lbMessage = new Sys.Preview.UI.Label($get('lbMessage'));
g_lbMessage.initialize();
}
function getServerHelloString()
{
HelloworldService.GetHelloWorldString(g_tbName.get_text(), cb_getServerHelloString);
}
function cb_getServerHelloString(result)
{
g_lbMessage.set_text(result);
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<label for="tbName">
<asp:ScriptManager id="ScriptManager1" runat="server">
<services>
<asp:ServiceReference Path="HelloworldService.asmx"></asp:ServiceReference>
</services>
<Scripts>
<asp:ScriptReference Assembly="Microsoft.Web.Preview" Name="PreviewScript.js" />
</Scripts>
</asp:ScriptManager><br />
Your Name:</label><input id="tbName" type="text" />
<input id="btnSayHello" type="button" value="Say Hello From Server!" />
<div id="lbMessage"></div>
</div>
</form>
</body>
</html>
HelloworldService.cs
//C# code
using System;
using System.Web;
using System.Collections;
using System.Web.Services;
using System.Web.Services.Protocols;
/// <summary>
/// HelloworldService 的摘要说明
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService()]
public class HelloworldService : System.Web.Services.WebService {
public HelloworldService () {
//如果使用设计的组件,请取消注释以下行
//InitializeComponent();
}
[WebMethod]
public string GetHelloWorldString(string name)
{
return string.Format("Welcome to ASP.NET AJAX world, {0}!. Now it is {1}.",
name, DateTime.Now);
}
}
web.config
<system.web>
<httpHandlers>
<remove verb="*" path="*.asmx"/>
<add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory,System.Web.Extensions,Version=1.0.61025.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35"/>
<add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory,System.Web.Extensions,Version=1.0.61025.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35"/>
<add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler,System.Web.Extensions,Version=1.0.61025.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35" validate="false"/>
</httpHandlers >
</system.web>