通过 ASP.NET AJAX Extensions 实现脚本服务有两种方式——使用特殊类型的 ASP.NET Web 服务和通过页面方法。前一种情况下,您只需设计和构建一个链接到 ASMX 资源的类:
<%@ WebService Language="C#" CodeBehind="~/App_Code/TimeService.cs" Class="IntroAjax.WebServices.TimeService" %> |
该类可以选择从 WebService 类继承,并且必须用新的 ScriptService 属性加以修饰:
[ScriptService]
public class TimeService : System.Web.Services.WebService
{
...
}
|
每个可调用脚本的方法均声明为公共方法,并标记有通常的 WebMethod 属性。
页面方法只不过是在单个 ASP.NET 页面上下文中定义的公共、静态方法,每个方法都标记为 WebMethod。只能从宿主页面中调用它们。除了存储不同之外,对 Web 服务或页面方式的调用均由 ASP.NET AJAX 环境以相同方式进行处理。
您必须清楚,AJAX 服务代表后端的一部分。从 WS-* Web 服务意义上讲,它们并不是公共 Web 服务,Web 服务都是通过 WSDL 脚本完整记录并可通过携带 SOAP 数据的 POST 命令进行访问。AJAX 服务是真正的本地服务,通常在调用它们的同一个应用程序中进行定义。然而,它们也可以在不同的 Web 应用程序甚至不同的网站上,前提是它们位于同一个域。
通过启用 ASP.NET AJAX 运行时以接受对服务的调用,ScriptService 属性扮演了一个关键角色。如果没有 ScriptService 属性,当您试图进行调用时,服务器上就会引发异常。图 2 显示当一个 AJAX 页面链接到未标记该属性的服务时所返回的消息。注意,图中显示的页面永远不会显示给任何用户。当连接到声明使用此类服务的 ASP.NET AJAX 页面时,您确实会收到全部该标记。该标记返回 HTTP 500 错误代码,因为 ASP.NET 内部机制拒绝处理缺少该属性的 ASP.NET Web 服务进行的脚本调用。
默认情况下,AJAX 服务方法只能使用 POST 动词调用并返回 JSON 格式的数据。然而,通过使用各服务方法中可选择的 ScriptMethod 属性,可以更改这些设置。图 3 详细说明了 ScriptMethod 属性所支持的参数。返回到客户端的数据可以更改为 XML,甚至可以添加对 GET 请求的支持。但我已说过,这种表面看起来无恶意的更改可能会为攻击者提供新的机会,且增加了跨站点调用该方法的可能性。下列代码段显示了一个 Web 服务方法的定义:
[WebMethod]
[ScriptMethod]
public DateTime GetTime()
{
...
}
如果您不准备更改任何默认设置(多数情况下我建议这样做),则可以忽略 ScriptMethod 属性。不过,WebMethod 属性是必选项。
ASP.NET AJAX 服务和 SOAP
一旦创建了 AJAX Web 服务,它就发布为 ASMX 资源。默认情况下,它是公共 URL,可以由 AJAX 客户端使用,也可以由 SOAP 客户端及工具发现和使用。不过,您可以选择同时禁用 SOAP 客户端及工具。只需在承载服务的 ASP.NET 应用程序的 web.config 文件中输入下列配置设置即可:
这个简单的设置禁用了为 ASP.NET 2.0 Web 服务定义的任何协议(特别是 SOAP),并让服务仅回复 JSON 请求。注意,当这些设置开启时,您无法再通过浏览器的地址栏调用 Web 服务来进行快速测试。同样,您也不能请求 WSDL 向 URL 中添加 ?wsdl 后缀。
为了在 Web 应用程序中启用 ASP.NET AJAX,必须在 web.config 文件中包含下列设置:
最后,不管表面如何,没有任何必要让 SOAP 介入 ASP.NET AJAX 服务。但对 SOAP 客户端的支持是得到保证的,除非在 web.config 文件中明确禁用。
要使 ASP.NET AJAX 服务按预期正常工作,传入请求的内容类型 HTTP 头必须设置为 application/json。对于通过"SCRIPT"标记实施的跨站点攻击来说,这还是极好的补救措施。
调用 AJAX 服务
要调用 AJAX 服务,AJAX 客户端会遵从在 Windows 和传统的 ASP.NET 应用程序中引用 Web 服务的相同模式。一个代理类在本地提供与远程服务相同的接口。在 ASP.NET AJAX 应用程序中,此代理是一个 JavaScript 类,当页面下载后,由运行库生成。
JavaScript 代理类具有与脚本服务相同的名称和许多附加属性。它的特征是有一组相同的方法,只不过采用了稍有扩展的签名。一般而言,您没有必要探究代理类的源代码。不过,如果您想看一下它的结构,则可从浏览器的地址栏中尝试调用下列 URL:
http://.../service.asmx/js
浏览器将下载一个 JavaScript 文件,您可以将其保存到本地磁盘,供以后详阅。
JavaScript 代理类从一个名为 Sys.Net.WebServiceProxy 的基类继承而来。它提供了进行 JSON 调用的基本功能。本专栏的代码下载提供一个 Web 服务的代理类,它具有下列接口:
interface ITimeService
{
DateTime GetTime();
string GetTimeFormat(string format);
}
JavaScript 代理类的特征是具有图中列出的属性。除了常规的一组参数之外,每个镜像的方法还有三个参数。这三个参数分别是:方法成功时所要调用的回调函数、方法失败或超时情况下所要调用的回调函数、传递给两个回调的上下文对象。通过图中显示的三个与默认相关的属性,您可以对多次调用重复使用同一个函数(比如处理错误的唯一 JavaScript 函数)。下面是从 ASP.NET AJAX 页面调用一个远程 AJAX 服务的一些示例代码:
function getTime()
{
IntroAjax.WebServices.TimeService.GetTimeFormat(
"ddd, dd MMMM yyyy [hh:mm:ss]", onMethodComplete);
}
function onMethodComplete(results)
{
$get("Label1").innerHTML = results;
}
|
在方法调用结尾(无论结果如何)调用的回调具有下列原型:
function method(results, context, methodName)
context 参数代表调用时指定的上下文对象。methodName 参数是一个设为服务方法名称的字符串。最后,对于成功调用时所调用的回调,results 参数是包含 JavaScript 版本的方法返回值的对象。对于失败的回调,此参数则代表 Sys.Net.WebServiceError 对象。
构建用户界面
AJAX 完全是关于最广泛意义上的用户体验——连贯的感受、无闪烁更新、界面设施、资源聚合、实时数据等等。但您只能利用浏览器和它的一套可编程性功能,主要是浏览器的对象模型、DOM 实现、对 DHTML 扩展的支持、CSS、JavaScript 和插件。
JavaScript 是构建和操纵 UI 的主要工具。用户界面任务的典型模式要求客户端使用 JavaScript 调用远程服务、接收 JSON 数据或可能是 XML 数据,然后重新整理页面以显示更改。
如此简单的模型在应用到实际应用程序的规模和复杂性时未必有效。随着 UI 的结构变得日益复杂化,重新整理页面来合并远程调用后新来的数据所带来的问题不可小觑。关键是,一个复杂的 UI 成为问题的临界点在哪里?
从根本上说,每个实际应用程序(尤其是业务线应用程序)必须依赖三个基本的用户界面功能:布局、数据绑定和样式。除了通过 CSS 支持某些样式外,JavaScript 环境不支持任何这些用户界面功能。此外,在大量的编程常因浏览器的细微错误和粗劣的编程而导致内存问题之类的情况下,JavaScript 还是一种解释性语言。
考虑一个比较常见的简单情形——对数据网格分页。网格归根到底就是十分复杂的表,浏览器必须为每个请求分析和呈现它。第一次处理页面时,用户很难衡量此呈现操作的成本,因为它已合并到整体页面下载过程中。但是,一旦对新网格页面提出 AJAX 回发请求,更新浏览器窗口的成本就会立即显现。浏览器收到包含对象集合的 JSON 字符串,而且必须将该集合转换成新的表。在客户端必须构建庞大的 HTML 字符串,在一些内存缓冲区中组织文本。如果没有差错,相同的字符串随后还必须以图形方式呈现。
当完成如此密集的操作后,您会发现响应时间并非如此理想。对于类似上述的情形,要找出有效的解决方案,需要具备中等以上的 JavaScript 和 DHTML 技能。
一个替代方法是在服务器上预先生成一些标记。这样,远程服务不仅返回数据,而且还合并标记信息。在服务器上,标记是通过已编译的代码来构建的,因此可以更容易地调试和测试它,而且您可以用更强大的编程工具来添加可访问性功能。另一方面,线路上将传输更多的数据(但是请记住,数据量仍远少于常规 ASP.NET 回发)。
底线就是,无论是从性能还是从开发角度考虑,为了有效地创建切实可行的用户界面,客户端需要更强大的工具。完备的部件和控件库对任何开发人员来说都十分必要。但是,即使经过最完美优化的库对于打破解释性语言(比如 JavaScript)的固有限制也无能为力。也许 Silverlight 最终会向 Web 开发人员提供他们所希望的用于下一代 Web 和 AJAX 应用程序的客户端环境;Silverlight 是一个 Microsoft 跨平台浏览器插件,它结合了 Windows® Presentation Foundation (WPF) 框架的一个子集。但是 Silverlight 是一个外部插件,需要单独下载,而且尚未成熟。1.0 版刚发布不久,若要用它构建真正实用的 Web 应用程序的表示层,还需要一些更高级的功能。
这一切意味着什么
部分呈现是实现 AJAX 最简便的方法。它非常适合于将 AJAX 功能添加到旧式应用程序中,您不必花时间、预算来重新设计这些应用程序,也不会有重新进行设计的愿望。从体系结构的角度上说,部分呈现是对当今 ASP.NET 的智能化扩展,而且保留了相同的应用程序模型和底层引擎。
纯 AJAX 体系结构是基于客户端与服务器的松散耦合,即实质上彼此独立的两个世界通过 HTTP 线路就 JSON 交换消息连接了起来。在纯 AJAX 体系结构中有一个基于服务的后端和一个 JavaScript 驱动的前端。构建有效的 HTML UI 完全取决于您或您选择的控件库。不过,这种分离机制使 Web 开发人员能够继续采用 Silverlight 等新兴技术创建交互性更强的用户界面,而不受服务器平台的限制。
Dino Esposito是 Solid Quality Learning 的一位导师,也是即将出版的“Programming ASP.NET 3.5 Core Reference”(ASP.NET 3.5 技术内幕)(Microsoft Press, 2007) 一书的作者。Dino 定居于意大利,并经常在世界各地的业内活动中发表演讲。您可访问他的博客,网址为 weblogs.asp.net/despos。
| 共3页: 上一页 [1] [2] 3 | |||||
|