附录
0、它是如何工作的
利用 Ajax包装器,ASP.NET开发人员可以快速方便的部署很容易利用AJAX功能的页面。
Ajax依靠代理(broker)指派和处理往返服务器的请求,对此,包装器的目的是隐藏 XmlHttpRequest对象的实现,包装器本身通过将.NET函数标记为 Ajax方法来工作。标记之后,AJAX就创建对应的JavaScript函数,这些函数(和任何JavaScript函数一样)作为代理可以在客户端使用 XmlHttpRequest调用。这些代理再映射回服务器端函数。
假设有一个.NET函数:
1
2
3
|
ublic int Add( int firstNumber, int secondNumber) { return firstNumber + secondNumber; } |
包装器将自动创建名为“Add”、带有两个参数的JavaScript函数。使用JavaScript(在客户机上)调用该函数时,请求将传递给服务器并把结果返回给客户机。
1、创建服务器端函数
⑴、项目中引用 Ajax.dll文件。
⑵、编写函数代码
1
2
3
4
5
6
7
8
9
10
|
namespace ForAjax { public class Example { [Ajax.AjaxMethod()] public static int ServerSideAdd( int firstNumber, int secondNumber) { return firstNumber + secondNumber; } } } |
函数中包含 [Ajax.AjaxMethod()]属性集。该属性告诉包装器这些方法创建javaScript代理,以便在客户端调用。
2、客户端调用
⑴、网站中引用 Ajax.dll及 服务器项目文件。
⑵、web.config中建立HttpHandler
1
2
3
4
5
6
|
< configuration > < system.web > < httpHandlers > < add verb = "POST,GET" path = "ajax/*.ashx" type = "Ajax.PageHandlerFactory, Ajax" /> </ httpHandlers > </ system.web > </ configuration > |
注:在 IIS7上部署。
1
2
3
4
|
< system.webServer > < handlers > < add name = "ajax" verb = "POST,GET" path = "ajax/*.ashx" type = "Ajax.PageHandlerFactory, Ajax" /> </ handlers > </ system.webServer > |
⑶、客户端页面调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<%@ Page Language= "C#" AutoEventWireup= "true" CodeFile= "Default.aspx.cs" Inherits= "_Default" %> <html> <head> <script language= "javascript" src= "ajax/common.ashx" ></script> <script language= "javascript" src= "ajax/ForAjax.Example,ForAjax.ashx" ></script> <script language= "javascript" > var response = Example.ServerSideAdd(100,99); alert(response.value); </script> </head> <body"> <form id= "form1" > </form> </body> </html> |
其中,"ajax/ForAjax.Example,ForAjax.ashx" 为 "ajax/Namespace.PageClass,AssemblyName.ashx"格式。可以在浏览器中手工导航到src路径(查看源代码,复制粘贴路径)检查是否一切正常。
通过 web.config,我们已经保证所有对 ajax/*.ashx的请求都由自定义的 Ajax包装器处理。包装器负责创建带有两个参数的 JavaScript函数 Sample.ServerSideAdd以供前台调用。
3、回调函数
1
2
3
4
5
6
7
8
9
|
Sample.ServerSideAdd(100,99, ServerSideAdd_CallBack); function ServerSideAdd_CallBack(response){ if (response.error != null ){ alert(response.error); return ; } alert(response.value); } |
其中响应对象 response公开了三个主要性质
- Value——服务器端函数实际返回的值(无论是字符串、自定义对象还是数据集)。
- Error——错误消息,如果有的话。
- Request——xml http请求的原始响应。
- Context——上下文对象。
4、处理类型
Ajax包装器不仅能处理ServerSideAdd函数所返回的整数。它目前支持 integers、strings、double、booleans、DateTime、DataSets和DataTables,以及自定义类和数组等基本类型。其他所有类型都返回它们的ToString值。
⑴、返回的 DataSets
和真正的.NET DataSet差不多。假设一个服务器端函数返回DataSet,我们可以通过下面的代码在客户端显示其中的内容:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
<script language= "JavaScript" > //Asynchronous call to the mythical "GetDataSet" server-side function function getDataSet(){ AjaxFunctions.GetDataSet(GetDataSet_callback); } function GetDataSet_callback(response){ var ds = response.value; if (ds != null && typeof (ds) == "object" && ds.Tables != null ){ var s = new Array(); s[s.length] = "<table border=1>" ; for ( var i=0; i<ds.Tables[0].Rows.length; i++){ s[s.length] = "<tr>" ; s[s.length] = "<td>" + ds.Tables[0].Rows[i].FirstName + "</td>" ; s[s.length] = "<td>" + ds.Tables[0].Rows[i].Birthday + "</td>" ; s[s.length] = "</tr>" ; } s[s.length] = "</table>" ; tableDisplay.innerHTML = s.join( "" ); } else { alert( "Error. [3001] " + response.request.responseText); } } </script> |
⑵、返回自定义类
Ajax还可以返回自定义类,唯一的要求是必须用 [Serializable()]属性标记。假设有如下的类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
[Serializable()] public class User { private int _userId; private string _firstName; private string _lastName; public int userId { get { return _userId; } } public string FirstName { get { return _firstName; } } public string LastName { get { return _lastName; } } public User( int _userId, string _firstName, string _lastName) { this ._userId = _userId; this ._firstName = _firstName; this ._lastName = _lastName; } public User() { } [AjaxMethod()] public static User GetUser( int userId) { //Replace this with a DB hit or something :) return new User(userId, "Michael" , "Schwarz" ); } } |
我们可以通过调用 RegisterTypeForAjax注册 GetUser代理:
1
2
3
|
private void Page_Load( object sender, EventArgs e) { Utility.RegisterTypeForAjax( typeof (User)); } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<script language= "javascript" > function getUser(userId){ User.GetUser(GetUser_callback); } function GetUser_callback(response){ if (response != null && response.value != null ){ var user = response.value; if ( typeof (user) == "object" ){ alert(user.FirstName + " " + user.LastName); } } } getUser(1); </script> |
响应中返回的值实际上是一个对象,公开了和服务器端对象相同的属性(FirstName、LastName和UserId)。
⑶、返回 Unicode字符
Ajax .NET包装器能够从服务器向客户机返回Unicode字符。为此,数据在返回之前必须在服务器上用html编码。比如:
1
2
3
4
5
6
7
8
9
|
[Ajax.AjaxMethod] public string Test1( string name, string email, string comment) { string html = "" ; html += "Hello " + name + "<br>" ; html += "Thank you for your comment <b>" ; html += System.Web.HttpUtility.HtmlEncode(comment); html += "</b>." ; return html; } |
⑷、自定义转换器
我们已经看到,Ajax .NET包装器能够处理很多不同的.NET类型。但是除了大量.NET类和内建类型以外,包装器对不能正确返回的其他类型仅仅调用ToString()。为了避免这种情况,Ajax .NET包装器允许开发人员创建对象转换器,用于在服务器和客户机之间平滑传递复杂对象。
5、会话访问
1
2
3
4
5
6
7
|
[Ajax.AjaxMethod(Ajax.HttpSessionStateRequirement.Read)] public void DocumentReleased() { if (System.Web.HttpContext.Current.Session[ "DocumentsWaiting" ] == null ) { //... } } |