目录
在 ASP.NET 中实现 AJAX 的方法
实现 ASP.NET AJAX 的直接方法
UpdatePanel 和侦听器模式
控制频带外调用
页面方法与 Web 服务方法
我实现 ASP.NET AJAX 的方法
除非您在过去的 12 个月里没有上过网 - 也许是到远方的热带小岛度假去了或参加了真人秀比赛 – 否则您应该对 AJAX 有所耳闻。但是,保险起见,我还是简要介绍一下。
首先,缩写词 AJAX 代表 Asynchronous JavaScript and XML(异步 JavaScript 和 XML)。接着是它的用途:它是一项真正的突破,有了 AJAX,那些以往看来无法实现或不切实际的解决方案都将成为可能。最后是 AJAX 的组成。本质上,这不是一项技术,而是一个概括性术语,表示利用已面市若干年的客户端 Web 技术(例如 JavaScript、级联样式表 (CSS)、DHTML 和 XMLHttpRequest)的强大组合来构建大量浏览器应用程序。
目前可用的大部分浏览器均支持功能的普通集 - Web 开发人员可使用这些功能来构建交互性强、刷新快速且能在客户端上执行大量工作的应用程序。利用这些功能,AJAX 应用程序能够为用户带来与使用桌面应用程序相似的极佳体验。此外,AJAX 也使创建“混合”应用程序比以前更容易。混合应用程序是一种 Web 应用程序,它将来自多个来源的信息结合在一起(例如,将 Microsoft? Virtual Earth? 与房地产销售信息结合起来,以创建有用的房地产工具)。
但是,我觉得,正因为 AJAX 的丰富性和重要程度,它反而会被人们很快遗忘。不可思议?之所以这样认为,原因是我觉得 AJAX 会被这个行业中的每个人所消化吸收,从而变成无需思索便会执行的日常生活中的基本组成部分 - 就像现在我们觉得没必要强调 XML 或 HTTP 的使用一样。
Microsoft ASP.NET AJAX(以前称为“Atlas”)在 2005 年 9 月的 Microsoft Professional 开发人员会议上公诸于众,它为 ASP.NET 2.0 增添了许多新能力(请参阅 ajax.asp.net),所有这些能力都是为了简化向网站添加基于 AJAX 的功能的方法。在本月的专栏中,我将详细介绍 ASP.NET AJAX,深入探讨它的一些关键功能。阅读本专栏之前,您应具备相关基本概念和工具的知识。有关详细介绍,请参阅 MSDN? 杂志 2006 年 7 月号上的文章“Atlas 出炉:ASP.NET Atlas 为您期待已久的 AJAX 样式的网站提供支持”,作者 Matt Gibbs。此外,还可参阅提要栏中的“目前仍同步”以了解其他相关信息。
在 ASP.NET 中实现 AJAX 的方法
使用 AJAX 可构建哪些新的应用程序功能?或者,明确点说,使用异步 JavaScript 调用和浏览器的对象模型可构建什么功能?支持 AJAX 功能的主要技术有三种:远程方法调用、客户端数据绑定和视觉效果。远程方法调用听起来有点太含糊,所以本文中仅对其中的部分页面回发和频带外请求进行探 讨。
如何将新的或现有的 ASP.NET 应用程序转换为 AJAX 应用程序?据统计,目前可用于 AJAX 开发的框架超过 100 个 - 它们支持多种平台并采用不同的编程方法。大体上,我趋向根据这些 AJAX 框架的功能将它们分为三个主要类别:回调框架、UI 框架和完整框架。
回调框架由客户端和服务器库的简单集合组成。它只允许您从客户端调用服务器端代码片段,以序列化格式移动输入和输出参数。典型的 UI 框架是从现有的专业控件库演变而来,它提供高级网格控件、图表控件和树控件。这些控件支持异步回发和在客户端上注入用于自动刷新页面的 JavaScript 代码。完整框架则提供包含控件和应用程序服务在内的丰富编程模型,更适宜同时用在客户端和服务器上。Microsoft ASP.NET AJAX 属于第三种类别。
如果您使用的是商业控件套件,那么升级到新一代支持 AJAX 的版本后您不会有任何的不适应感觉。如果您完全在内部开发应用程序,并要保护表示层和后端层,那么完整框架是最可行的选择。而简单框架则只用于将快速回调 功能添加到现有 ASP.NET 应用程序(版本 1.1 和 2.0)中。
ASP.NET 2.0 提供内置脚本回调 API,这一点我已在本专栏中多次提到,例如“最先进的技术:ASP.NET 中的脚本回调”和“Cutting Edge:Custom Script Callbacks in ASP.NET”(英文)。在本专栏附带的代码中,包括一个用于远程方法调用的非常简单的 AJAX 框架演示。它仅包含 50 行代码,一部分用 JavaScript 编写,一部分用托管代码编写。当然,它无法与 ASP.NET AJAX 相比,但它可用作将基本 AJAX 功能添加到 ASP.NET 1.1 应用程序的核心代码。
实现 ASP.NET AJAX 的直接方法
ASP.NET AJAX 包含两种截然不同(但不互相排斥)的 API:客户端和服务器。您可以通过直接客户端编程、传统服务器端编程或这两者的任意组合构建 AJAX 功能。本质上,任何基于 AJAX 的页面都需要一些客户端 JavaScript 代码来处理浏览器的文档对象模型 (DOM) 和任何特定于应用程序的扩展。但不必将这类脚本代码编写工作留给 ASP.NET 程序员。事实上,框架可生成专门设计的脚本代码作为服务器端控件的输出。这种形式的间接页面更新是目前为止将 AJAX 功能添加到新的和现有的 ASP.NET 2.0 页面的最简单方法。在 ASP.NET AJAX 中,页面更新可由服务器控件(UpdatePanel 控件)所自动插入的一段客户端代码来管理。
UpdatePanel 控件代表 ASP.NET AJAX 以服务器为中心的编程模型的神经中枢。它允许您执行服务器端代码并将已更新标记返回到客户端浏览器。您可能想知道这与传统的回发有什么不同。它们的区别在 于回发的实现方式 – 传统的回发是整页刷新,而 UpdatePanel 控件会设法发送一个频带外请求以取得刷新标记,并在响应就绪后更新 DOM 树。
ASP.NET 以客户端为中心的编程模型的重心是放置远程端点(通常为 ASP.NET Web 服务和 Windows? Communication Foundation 服务,但也可能是其他内容)调用的能力。直接从客户端浏览器启动时,对远程端点的调用需要 JavaScript 代理和 JavaScript 代码片段。客户端数据绑定可视为传统 JavaScript 运行时和 DOM 的扩展。在纯粹的客户端编程风格中,首先会连接到远程端点,然后下载数据,并将数据绑定到 DOM 子树。模板结构和一些状态信息保存在客户端上,只有原始数据从服务器移动到客户端上。
在 ASP.NET AJAX 中有三种主要的编程方法。图 1 概要介绍了这些工具以及它们的适用环境。
Figure1在 ASP.NET AJAX 中编程的方法
方法 描述 使用
UpdatePanel 包含一组服务器控件,监控这些控件的回发和呈现过程。通过脚本拦截和处理任何由所包含控件产生的回发请求。页面的更改会通过 DHTML 来应用。 如果您的团队不擅长 JavaScript,或者您希望将公开给客户端编程的信息降到最少,则使用此方法。如果您需要保护应用程序中任何敏感的业务逻辑,也建议使用 UpdatePanel。
远程方法调用 概括性术语,表示异步调用页面方法及本地和外部 Web 服务。调用通过 JSON 数据流以独立于类型的方式移动输入参数和接收返回值。要触发调用并将更改应用于客户端,需要强类型化 JavaScript 代码。 当您需要使用以异步方式触发和控制远程操作的智能客户端时,请使用此方法。此方法需要 JavaScript 编码来处理返回值和更新当前 DOM 中任何受结果影响的部分。
客户端数据绑定* 完全用 AJAX JavaScript 编写的两个客户端控件,用于实现基于模板的绑定。它们是用于多记录视图的 ListView 和用于单记录视图的 ItemView。这两个控件和客户端数据源以及筛选组件组合在一起。 当您需要 DHTML 应用程序的现代型跨浏览器版本时,可以使用此方法。绑定客户端数据后,最后得到的页面包括一厚层的 JavaScript 和/或 XML Script,并且没有任何托管代码(脚本管理器控件除外)。
UpdatePanel 和侦听器模式
UpdatePanel 控件所代表的编程风格是:无需整页刷新,也无需客户端编程,即可更新页面内容。在 ASP.NET AJAX 术语中,这称为部分呈现。在支持此功能的组件中,UpdatePanel 控件是最显眼的一个。但是,在部分呈现的内部实现的背后,真正的中枢是 ScriptManager 控件。不过,UpdatePanel 控件依然是开发人员编写部分更新的页面时使用的主要工具。
可通过以下两种方法之一更新网页 - 手动单击“提交”按钮或以编程方式调用 DOM 表单对象的提交方法。在这两种情况下,浏览器都会冻结当前页面并向后端 Web 服务器发送新请求。然后传入的响应会替换现有内容。
UpdatePanel 控件在此过程起关联作用。它截获表单提交,捕获正在发送的任何信息,然后根据 XMLHttpRequest 通过频带外调用发送同样的信息。UpdatePanel 控件还会加入一些其他信息,以指示要在服务器上处理和呈现哪些控件,从而实现部分页面呈现。
侦听器模式完整描述了由 UpdatePanel 控件所导致的行为。该模式引用观察对象调用并在调用者和接收者之间注入自己代码的任何外部组件。这样,外部控件将完全控制操作,控制如何完成任务,并将有 效响应返回到调用者。图 2 说明在 ASP.NET AJAX 中此模式的实现。
图 2UpdatePanel 控件和侦听器模式
注入客户端页面的脚本代码为表单的 onsubmit DOM 事件注册一个处理程序。这个新处理程序只是将传统请求替换为用于完成 XMLHttpRequest 并传递其他信息的请求。特别是,它将负责回发的 UpdatePanel 控件名称加到现有输入字段列表中。下面是具有可分页网格的页面的修改内容:
ScriptManager1=UpdatePanel1|GridView1&
__EVENTTARGET=GridView1&
__EVENTARGUMENT=Page%241&
__VIEWSTATE=...&
__VIEWSTATEENCRYPTED=&
__EVENTVALIDATION=...
ScriptManager 伪参数引用负责回发的 UpdatePanel 控件的 ID。只有与指定 UpdatePanel 控件关联的控件才会刷新,它们的已修改标记以及已更新的视图状态信息会发送回浏览器。
部分呈现是各种 AJAX 框架中的常用功能,尽管内部实现方法可能有所不同。大部分差异与用来关联可更新控件与请求的方法有关。在 ASP.NET AJAX 中,可更新控件在最外面的容器控件(UpdatePanel 控件)中进行了分组。该容器内的所有内容都会呈现出来以进行标记 - 这代表当前所显示页面的增量。另一个方法是要求各个控件以编程方式在框架上注册,以呈现 AJAX 式回发。这与在 ASP.NET 2.0 中使用支持控件状态的控件时发生的情况类似。
与分组容器中的控件相比,更精确、灵活的方法是让每个控件决定如何呈现 AJAX 式回发。但是,您还需要其他源代码指令或使用临时控件。虽然适用于控件库和其他此类产品,此方法却不太适用于诸如 ASP.NET 之类的 Web 框架。
UpdatePanel 控件是从 System.Web.UI.Panel 派生而来的类。作为子 ASP.NET 控件的无 UI 容器,UpdatePanel 可包含任何 ASP.NET 服务器控件,不需要使用任何支持 AJAX 的特殊控件。通过使用 UpdatePanel,可以使用与传统的 ASP.NET 相同的应用程序模型和编程风格在服务器上完成 AJAX 编程。开发人员不必学习 JavaScript 或客户端 Microsoft AJAX Library。同样,他们也不会受到 XML Script 或浏览器 DOM 的任何影响。
将传统的 ASP.NET 页面转换为 AJAX 页面需要进行两步操作。首先将 ScriptManager 控件添加到页面中。然后使用 UpdatePanel 控件封装任何想要部分刷新和异步刷新的控件组。UpdatePanel 控件支持嵌套,可以动态创建。此外,ASP.NET 页面可包含的 UpdatePanel 控件数目不受限制,可以是任意数量。
以下两种情况会触发实际更新:子控件回发时,以及发生特定外部事件时。通过触发器和其他属性,可以使每个 UpdatePanel 控件有条件地刷新内容。
使用 UpdatePanel 控件,您可以将 ASP.NET 页面逐步迁移到 AJAX,并且迅速完成此操作。实际上,同一个 ASP.NET 页面既可以使用 AJAX 式回发,也可以使用传统式回发。因此,UpdatePanel 必须随每个请求改变页面的视图状态。具体来说,就是将视图状态发送到服务器,更新视图状态以反映对选定控件的更改,然后将视图状态下载到客户端。对于事件 验证数据也会执行同样的操作。在客户端上不能更新视图状态和事件验证数据。因此,必须将视图状态和事件验证数据发送回服务器,检查是否已更改并做适当的更 新。在 AJAX 式和传统式回发中,要在实现成功回发的同时维护页面状态的一致性,则客户端一定要具有视图状态和事件验证数据的最新副本。
从根本上来说,UpdatePanel 是学习 ASP.NET AJAX 的最简单方法,它涉及的升级和迁移工作最少,并且可在传统页面和 AJAX 页面之间进行完全的互操作。当您使用可更新面板时,页面刷新会更迅速。有时,更新的速度甚至会快得用户根本无法意识到。因此,显示运行情况的面板将会非常 繁忙,但可能仍不够用。诸如 UpdateProgress 控件的繁忙面板主要用于长期任务,而不是让用户了解所显示内容进行了哪些更改。若要为用户提供有关此类更改的反 馈,UpdatePanelAnimation 扩展器(在 AJAX Control Toolkit 的最新 CTP 中定义)是一款更好的工具。您可以查看正在运行的示例。扩展器以动画效果显示回发期间 UpdatePanel 所包含的区域。另外,您还可以在扩展器上为正在更新和已更新事件指定动画效果。但是,请注意,您必须单独安装 AJAX Control Toolkit,因为它没有整合到 ASP.NET AJAX Extensions 下载包中。
控制频带外调用
如果您很擅长 JavaScript,并想要尝试从客户端直接调用服务器,那么您一般可使用下列两种方法:使用 Web 服务和调用静态页面方法。
通过在脚本管理器上注册 ASMX Web 服务,指示 ASP.NET AJAX 基础结构生成 JavaScript 代理类并将其注入客户端页面。若要查看代理类,可在地址栏(本地计算机)中键入 Web 服务的 URL,随后键入 /js 后缀。下面是一个 Web 服务的 JavaScript 代理的示例,其中有两个公共方法。为便于阅读,代码已进行了简化:
Type.registerNamespace('Samples.MyWebService');
Samples.MyWebService = new function()
{
this.appPath = "http://YourServer/AjaxDemo/";
var cm = Sys.Net.ServiceMethod.createProxyMethod;
cm(this, "LookupCustomer", "id");
cm(this, "LookupAllCustomers");
}
可使用此代码从脚本标记调用 Web 服务。它使用传统的代理模式,整体机制与您在服务器的传统 ASP.NET 或 Windows 应用程序中使用 Web 服务时的机制完全相同。
但是,仍有一些需要注意的问题。您想从客户端调用什么类型的服务器端代码?或者从另一个角度,您想从客户端调用 Web 服务的什么类型的操作?从 AJAX 页面调用的 Web 服务会将一些业务逻辑暴露给客户端页面。可以从 Internet 调用 Web 服务的公共端点,并且没有任何内置安全层可对应用程序逻辑提供保护。这个漏洞早已为人所熟知。
ASP.NET AJAX 为开发人员提供了通过 Web 服务公开某些应用程序逻辑的能力。一旦在 Internet 上发布,该逻辑(不受任何安全层保护)就可供任何调用者使用。一般来说,您应只公开那些能够在 Internet 中安全使用的数据和逻辑。如果您只是编写和调用返回产品目录的 Web 服务,可能不会产生任何实际问题。但公开业务逻辑层 (BLL)(例如信用卡验证过程)就不是您应该做的事了。
ASP.NET AJAX 会导致您使用 Web 服务向客户端页面公开 BLL,以供直接使用。您应将 AJAX Web 服务视为一种不重要的用户界面层 BLL。任何真正敏感的 BLL 块都应该使用传统的回发或 UpdatePanel 控件进行调用。
若要将 Web 服务直接链接到 ASP.NET AJAX 页面,这些 Web 服务必须是本地 Web 服务,驻留在与调用者页面相同的 Web 应用程序中。之所以这样要求,有两个原因。第一,Web 服务必须由知道如何处理每个请求上所附加 /js 后缀的 ASP.NET AJAX 应用程序支持。但是,您也可以使用其他 ASP.NET AJAX 应用程序来托管 Web 服务。在这种情况下,您的客户端调用可能会与当前浏览器中较严格的安全设置(防止跨站点调用)冲突。
页面方法与 Web 服务方法
将服务器代码与 ASP.NET AJAX 页面绑定的另一种方法是调用页面方法。可调用的页面方法是一种公共静态方法(在 Visual Basic? .NET 中为共享方法),这种方法在源代码类中定义,并使用 Web 服务方法所用的 WebMethod 属性进行修饰。目前,这仅限于 ASPX 页面 – 包括内嵌式代码和源代码 - 但将来可能扩展到用户控件和自定义控件。
我应特别指出,ASMX Web 服务和页面方法需要不同的设置。特别地,您必须在脚本管理器中注册 Web 服务,您还必须安装脚本 HTTP 模块,才能运行页面方法。图 3 显示 web.config 文件中所需的内容。
Figure3ASP.NET AJAX 的 Web.config 中的更改
<microsoft.web>
<scripting>
<webServices>
...
</webServices>
</scripting>
</microsoft.web>
<system.web>
<httpHandlers>
<remove verb="*" path="*.asmx"/>
<add verb="*" path="*.asmx"
type="Microsoft.Web.Script.Services.ScriptHandlerFactory"
validate="false"/>
</httpHandlers>
<httpModules>
<add type="Microsoft.Web.UI.ScriptModule" name="ScriptModule"/>
</httpModules>
</system.web>
为了注册 Web 服务和强制生成代理,您需要执行下面的代码:
<asp:ScriptManager ID="scriptManager1" runat="server">
<Services>
<asp:ServiceReference Path="~/WebServices/MyDataService.asmx" />
</Services>
</asp:ScriptManager>
此外,还需要其他属性来修饰 Web 服务类。尤其是,要生成 JavaScript 代理类,需要 ScriptService 属性;而对您计划使用的每个自定义类型(泛型类型除外),则需要 GenerateScriptType 属性。图 4 显示了一个示例。
Figure4ASP.NET AJAX Web 服务方法
namespace Samples
{
[WebService(Namespace = "http://samples.ajax/")]
[ScriptService]
[GenerateScriptType(typeof(Customer))]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class MyDataService : System.Web.Services.WebService
{
public MyDataService() {}
[WebMethod]
public Customer LookupCustomer(string id)
{
return CustomerManager.Load(id);
}
[WebMethod]
public CustomerCollection LookupAllCustomers()
{
return CustomerManager.LoadAll();
}
}
对于 Customer 类型,必须应用 GenerateScriptType;但对于从泛型 Collection<T> 类派生而来的 CustomerCollection,则不必应用,因为 ASP.NET AJAX 对该类型有内置支持:
public class CustomerCollection : Collection<Customer> {}
页面方法需要的 HTTP 模块联系 ASPX 请求的默认 HTTP 处理程序,并将呈现阶段重定向到执行特定方法并序列化返回值的自定义代码片段。
页面方法和 Web 服务方法这两种方法都帮助您访问后端 BLL。类似公开的 Web 服务方法,页面方法可以轻松地从浏览器的地址栏自动执行 – 这只需一些基本的 JavaScript Object Notation (JSON) 技能。因此,考虑到所要公开的 BLL 逻辑,您应象使用 WebMethods 一样小心使用页面方法。
最后,您是选择使用页面方法还是选择使用 Web 服务方法其实只是个人喜好而已。在这两种情况下,您都应生成一个外层,该层会在稍后路由到适当的 BLL 函数,如图 5 所示。只要您在每个页面中注册了服务的端点,就可以从任何页面调用 Web 服务方法。页面方法则只能从定义该方法的页面调用。目前,我个人更偏好使用页面方法。
图 5页面方法和 Web 服务方法的比较
ASP.NET AJAX Web 服务方法和页面方法都广泛使用 JSON 传送对象数据。作为轻量级数据交换格式,JSON 用于将对象序列化为字符串。由于其固有的简单性,JSON 既适合人类也适合计算机。能够读写 JSON 字符串的人要多于能够读写 SOAP 数据包的人。并且 JSON 也非常易于计算机解析和处理。
您可能会认为页面方法比 Web 服务的性能更高。毕竟,为了解析 Web 服务调用,ASP.NET 运行时必须解析 SOAP 数据包。但这并不完全正确。ASP.NET AJAX 会安装一个用于截取所有 ASMX 请求的定制的 HTTP 处理程序(请参阅图 3)。带有 /js 后缀的请求的处理方式不同,这些请求是直接与 JSON 负载及 Web 服务方法一起处理。因此,无论如何都不会包含任何 SOAP,请求的正文也只包含输入参数的 JSON 数据流。对于非 AJAX 请求,新 HTTP 处理程序只需将调用委托回理解 SOAP 的初始 ASP.NET 处理程序。
我实现 ASP.NET AJAX 的方法
考虑了所有因素后,我认为 UpdatePanel 是大多数开发团队可采用的最佳方法。它不排斥传统的 ASP.NET,因此您可以方便地修改现有页面。它也不复杂陌生,使用前不需要学习大量新知识。另外,UpdatePanel 能够为 BLL 提供与传统网页相同的保护级别,并且它完全支持运行冗长任务的异步 ASP.NET 页面。
最后一条忠告:避免混合使用各种 AJAX 平台。对于 JavaScript 内置对象扩展,ASP.NET AJAX 和其他框架之间可能会有冲突。更重要的是,不保证现在起作用的产品组合将来仍能使用。任何框架的任何新版本都可能引起新的冲突。
函数基础:内置函数
Python函数基础---参数、变量
python函数基础:嵌套函数、作用域、匿名函数、高阶函数、递归函数
三元运算、文件操作
Python终端如何输出彩色字体
文件处理: read、readline、 readlines()
16进制、编码问题
JSON 操作与转化
高并发和大型网站架构相关