5. [SimuPaie] 应用程序 – 版本 2 – AJAX / ASP.NET
5.1. 简介
AJAX(异步 JavaScript 和 XML)技术整合了一系列技术:
- JavaScript:在浏览器中显示的 HTML 页面可以嵌入 JavaScript 代码。如果用户未在浏览器中禁用 JavaScript 执行,该代码将由浏览器执行。这项技术自万维网早期便已存在,并得益于 AJAX,自 2005 年以来重新受到关注。
- DOM:文档对象模型。嵌入在 HTML 页面中的 JavaScript 代码可以通过对象树(即 DOM)的形式访问文档。文档中的每个元素(输入字段、命名的 div 标签、select 标签等)在树中都由一个节点表示。JavaScript 代码可以通过修改 DOM 来改变显示的文档。例如,它可以通过代表该字段的 DOM 节点来更改输入字段中显示的文本。
AJAX利用JavaScript在后台进行浏览器与服务器之间的交互。当响应按钮点击等事件时,浏览器会执行JavaScript代码,向服务器发送HTTP请求。该请求包含参数,用于告知服务器应执行的操作。 随后,服务器执行所请求的操作。作为响应,它向浏览器发送一个包含数据的 HTTP 数据流,从而实现当前显示页面的局部更新。这一过程通过文档的 DOM 以及文档中嵌入的 JavaScript 代码的执行来完成。服务器返回的数据可以采用多种格式:XML、HTML、JSON、纯文本等。
该技术的优势在于对显示文档的局部更新。这意味着:
- 客户端与服务器之间交换的数据更少,从而获得更快的响应
- 图形界面使用更流畅,因为用户操作不会触发整页重新加载。
在网络传输速度较快的内联网环境中,AJAX 能够创建行为与传统 Windows 界面相似的 Web 应用程序。例如,当列表中的选项发生变化时,系统可以立即对页面进行部分刷新以反映该变化。 页面无需完全重新加载这一特性,为用户带来了与 Windows 应用程序相同的流畅体验。对于响应时间可能较长的 Web 应用程序,AJAX 技术依然适用,但用户感知到的流畅度取决于网络性能。
AJAX面临的主要挑战在于JavaScript语言。该语言诞生于万维网的早期,
- 它被证明不适合面向对象编程。例如,它不是一种类型化语言。你无需声明所操作数据的类型。在这方面,它与Perl或PHP等语言相似。
- 目前尚无所有浏览器都认可的标准。每个浏览器都有自己专有的 JavaScript 扩展,这意味着为 Internet Explorer 编写的 JavaScript 代码可能无法在 Mozilla Firefox 中运行,反之亦然。
- 由于浏览器未提供强大的调试工具来调试其执行的 JavaScript 代码,因此调试工作十分困难。
JavaScript 的所有这些缺陷意味着,在 AJAX 出现之前,它很少被使用。一旦人们理解了在后台执行 JavaScript 代码的价值——即向 Web 服务器发出 HTTP 请求,并利用其响应通过 DOM 对显示的文档进行部分更新——开发团队便着手工作,并提出了无需开发人员编写 JavaScript 代码即可实现 AJAX 的框架。为了实现这一点,开发了能够适应客户端浏览器的 JavaScript 库。 将 JavaScript 代码插入发送至浏览器的 HTML 页面这一操作在服务器端完成,具体技术因所使用的 AJAX 框架而异。目前已有适用于 Java、.NET、PHP、Ruby 等平台的 AJAX 框架。AJAX 已集成到 Visual Web Developer 2008 中。
5.2. 位于 [ web-ui-ajax] 层中的 Visual Web Developer 项目
新版本是通过复制旧版本创建的。仅 [Default.aspx] 页面会被修改。
![]() |
- 在 [1] 中,使用 Windows 资源管理器复制项目文件夹 [pam-v1-adonet],并将其重命名为 [pam-v2-adonet-ajax]。然后,使用 Visual Web Developer 从该新文件夹 [2] 打开项目(文件 / 打开项目)
- 在 [3] 中,将其重命名为
![]() |
- 在新项目的属性中,修改程序集名称 [4] 和默认命名空间 [5]。
完成上述操作后,请将文件 [Default.aspx、Default.aspx.cs、Default.aspx.designer.cs、Global.asax、Global.asax.cs] 中的命名空间 [pam_v1] 替换为 [pam_v2],以确保与默认命名空间保持一致。例如,[Default.aspx] [6] 将变为:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="pam_v2._Default" %>
...
![]() |
- 在 [Default.aspx] 表单中添加 Ajax 组件(参见上文 [2])。
- 2A:任何 AJAX 项目都需要 <asp:ScriptManager> 组件
- 2B:<asp:UpdatePanel> 组件用于定义用户提交 POST 请求时需要刷新区域。该组件可避免整个页面重新加载。
- 2C:<asp:UpdateProgress> 组件用于在更新过程中显示文本或图像以通知用户,如下所示:
![]() |
- (待续)
- 2D:一个名为 LabelHeureLoad 的 Label 控件,用于显示页面 Load 事件处理程序运行时的时间。
- 2E:一个名为 LabelHeureSalaire 的 Label 控件,用于显示 [Salaire] 按钮的 Click 事件处理程序被执行时的时间。我们希望演示当点击 [Salaire] 按钮时,Ajax 不会重新加载整个页面。如前面的屏幕截图所示,两个 Label 中显示了两个不同的时间。
上述表单的 Ajax 化操作可直接在 [Default.aspx] 的源代码中通过添加 Ajax 扩展标签来实现:
...
<body style="text-align: left" bgcolor="#ffccff">
<h3>
Feuille de salaire
<asp:Label ID="LabelHeureLoad" runat="server" BackColor="#C0C000"></asp:Label></h3>
<hr />
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true" />
<asp:UpdatePanel runat="server" ID="UpdatePanelPam" UpdateMode="Conditional">
<ContentTemplate>
<div>
<table>
<tr>
...
<tr>
<td>
<asp:DropDownList ID="ComboBoxEmployes" runat="server">
</asp:DropDownList></td>
<td>
<asp:TextBox ID="TextBoxHeures" runat="server" EnableViewState="False">
</asp:TextBox></td>
<td>
<asp:TextBox ID="TextBoxJours" runat="server" EnableViewState="False">
</asp:TextBox></td>
<td>
<asp:Button ID="ButtonSalaire" runat="server" Text="Salaire" CausesValidation="False" /></td>
<td> <asp:UpdateProgress ID="UpdateProgress1" runat="server">
<ProgressTemplate>
<img src="images/indicator.gif" />
<asp:Label ID="Label5" runat="server" BackColor="#FF8000" EnableViewState="False"
Text="Calcul en cours. Patientez ...."></asp:Label>
</ProgressTemplate>
</asp:UpdateProgress>
<asp:Label ID="LabelHeureSalaire" runat="server" BackColor="#C0C000"></asp:Label></td>
</tr>
<tr>
...
</tr>
</table>
</div>
<br />
....
<table>
<tr>
<td>
Salaire net à payer :
</td>
<td align="center" bgcolor="#C0C000" height="20px">
<asp:Label ID="LabelSN" runat="server" EnableViewState="False"></asp:Label></td>
</tr>
</table>
</asp:Panel>
</ContentTemplate>
</asp:UpdatePanel>
</form>
</body>
</html>
- 第 8 行:任何支持 Ajax 的表单都必须包含 <asp:ScriptManager> 标签。此标签支持使用新的 Ajax 组件:
![]() |
- 可以通过双击上方的 [ScriptManager] 组件来添加 <asp:ScriptManager> 标签。请务必在源代码中确认该标签位于 <form> 标签之内。第 8 行中的 [EnablePartialRendering="true"] 属性默认情况下是缺失的。由于其默认值为 "true",因此严格来说并非必需。
- 第 9 行:<asp:UpdatePanel> 标签用于界定页面中在部分页面更新期间需要更新的区域。[UpdateMode="Conditional"] 属性表示该区域仅应在响应来自该区域内某个组件的 AJAX 事件时进行更新。 另一个取值是 [UpdateMode="Always"],这是默认值。使用此属性时,即使触发的 AJAX 事件源自另一个 UpdatePanel 区域中的组件,该 UpdatePanel 区域仍会系统性地进行更新。通常,这种行为是不希望看到的。
<asp:UpdatePanel> 标签支持两个子标签:<ContentTemplate> 和 <Triggers>。
- 第 10 行和第 53 行上的 <asp:ContentTemplate> 标签定义了页面中将进行部分更新的区域。
- 第 27–33 行:一个 Ajax 组件 <asp:UpdateProgress>,用于在页面更新过程中显示文本。例如,单击 [Salary] 按钮会在后台触发一个 POST 请求。浏览器不会显示沙漏图标,因此用户可能会继续使用该表单。 <asp:UpdateProgress> 标签会显示文本,提示页面正在更新。也可以显示图片。此处显示了一个动画图片(第 29 行)和文本(第 30–31 行):
![]() |
- 第 28–32 行:<ProgressTemplate> 标签界定了在包含 UpdateProgress 标签的 UpdatePanel 更新期间将显示的内容。
- 第 29–31 行:在 UpdatePanel 更新期间将显示的动画图像和文本。
- 第 5 行:LabelHeureLoad 标签位于 AJAX 启用区域之外
- 第 34 行:LabelHeureSalaire 标签位于 AJAX 启用区域内
protected void Page_Load(object sender, System.EventArgs e)
{
// time of each page load
LabelHeureLoad.Text = DateTime.Now.ToString("hh:mm:ss");
// initial request processing
if (!IsPostBack)
{
....
}
- 第 4 行:更新页面加载时间
protected void ButtonSalaire_Click(object sender, System.EventArgs e)
{
// hourly wage calculation
LabelHeureSalaire.Text = DateTime.Now.ToString("hh:mm:ss");
// data verification
....
}
- 第 4 行:更新工资计算时间
要完成 [Default.aspx] 页面,我们需要在页面中包含以下源代码第 4 行所引用的动画图像:
<td>
<asp:UpdateProgress ID="UpdateProgress1" runat="server">
<ProgressTemplate>
<img src="images/indicator.gif" />
<asp:Label ID="Label5" runat="server" BackColor="#FF8000" EnableViewState="False"
Text="Calcul en cours. Patientez ...."></asp:Label>
</ProgressTemplate>
</asp:UpdateProgress>
<asp:Label ID="LabelHeureSalaire" runat="server" BackColor="#C0C000"></asp:Label>
</td>
使用 Windows 资源管理器,我们将文件 [images/indicator.gif] 添加到项目文件夹 [1] 中:
![]() |
- 在 [2] 中,我们显示所有项目文件
- 在 [3] 中,选择 [images] 文件夹
- 在 [4] 处,我们将 [images] 文件夹添加到项目中
![]() |
- 在 [5] 中,[images] 文件夹已添加到项目中
- 在 [6] 中,我们将不属于该项目的文件隐藏起来
- 在 [7] 中,新建项目
5.3. 测试 Ajax 解决方案
运行项目(CTRL-F5)后,将显示以下页面:
![]() |
- 在 [1] 中,页面加载时间
测试应用程序,并验证[Salary]按钮不会导致页面完全重新加载。您可以通过比较[Salary]按钮点击处理所显示的时间[2](该时间与页面初始加载时间[3]不同)来观察这一点:
![]() |
将 ScriptManager1 组件的 EnablePartialRendering 属性设置为 False,然后重复上述测试:
![]() |
请注意,当前的行为与非 AJAX 页面相似。点击 [Salary] 按钮时,页面会完全重新加载。请使用其他浏览器重复进行测试。跨浏览器测试的目的是验证由 ASP/AJAX 服务器组件生成的 JavaScript 代码能否被不同浏览器正确解释。
最后,让我们重点说明 <asp:UpdateProgress> 标签的作用。在 [Default.aspx.cs] 文件中 [ButtonSalaire_Click] 过程的代码里,添加一条将过程暂停 3 秒的语句:
using System.Threading;
...
protected void ButtonSalaire_Click(object sender, System.EventArgs e)
{
// hourly wage calculation
LabelHeureSalaire.Text = DateTime.Now.ToString("hh:mm:ss");
// waiting
Thread.Sleep(3000);
// data verification
....
}
第 8 行代码会让执行 [ButtonSalaire_Click] 过程的线程等待 5 秒。完成后,让我们再次运行测试(在此之前,需将 ScriptManager1 组件的 EnablePartialRendering 属性设置为 True)。这次,在计算工资的过程中,我们会看到 [UpdateProgress] 中的文本以及动画图像:

5.4. 结论
前面的研究向我们展示了,可以在现有的 ASP.NET 应用程序中添加 AJAX 功能。ASP.NET AJAX 扩展的功能远不止我们刚才所见。欢迎读者访问网站 [http://ajax.asp.net]。










