分享
 
 
 

AJAX.NET用户开发指南

王朝c#·作者佚名  2006-11-24
窄屏简体版  字體: |||超大  

概述

AJAX依靠服务器作为中介来分发和处理请求。为了完成这项工作,.net封装类依赖于客户端的请求对象,而xmlHttpRequest对象被大部分的浏览器支持,因此使用这个对象是一个不错的解决方案。因为封装的目的是隐藏xmlHttpRequest的实现,故我们不讨论他的实现细节。

封装类是通过在.net的方法上增加AJAX属性标记来实现的,一旦被标记,AJAX创建客户端的javascript函数(这类似于客户端编写的javascript函数),并使用xmlhttprequest创建服务器代理,这个代理映射客户端的函数到服务器的处理函数。

复杂吗?不会的,让我们看看下面的简单例子,给出的.net 函数

'VB.Net

public function Add(firstNumber as integer, secondNumber as integer) as integer

return firstNumber + secondNumber

end sub

//C#

public int Add(int firstNumber, int secondNumber)

{

return firstNumber + secondNumber;

}

Ajax.net会立即自动的创建带有两个参数、名字为Add的javascript函数,当客户端调用这个javascript函数时,请求将从后台送到服务器端并从将计算结果返回给客户端。

初始安装

我们首先从如何把”.dll”安装到你的项目开始,当然,如果你了解如何使用,这一节可以跳过。

如果你还没有Ajax.dll,可以首先下载AJAX的最新版本。解压文件放到可以被你的项目引用的地方,在.net项目中,添加上对其的引用,然后就可以开始使用ajax.dll封装进行开发了。

如果你在安装引用时遇到了麻烦,可以参考这个链接的说明:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbcon/html/vbtskaddingremovingreferences.asp

设置HttpHandle

为了使其可以工作,第一步必须做的是在web.config中安装设置封装包的HttpHandle,不去详细解释HttpHandle是如何工作的,我们只需要了解他们可以用来处理asp.net请求。例如,所有的目的为*.aspx的请求可以通过System.Web.UI.PageHandlerFactory类发送到控制句柄,简单的说,我们把任何向ajax/*.ashx的请求发送到Ajax.PageHandlerFactory的请求处理句柄:

<configuration>

<system.web>

<httpHandlers>

<add verb="POST,GET" path="ajax/*.ashx" type="Ajax.PageHandlerFactory, Ajax" />

</httpHandlers>

...

<system.web>

</configuration>

上面的代码告诉asp.net把任何匹配到特定的路径(ajax/*.ashx)请求发送到Ajax.PageHandlerFactory产生的HttpHandle,而不再是默认的Handler factory。你不需要创建ajax子目录,这是一个只用来临时使用的虚拟的目录,因此别的HttpHandler可以用他们自己的目录来使用.ashx扩展名的文件。

配置页面

现在我们准备好开始代码编写了。打开一个新的网页或者已经存在的页面,在其codebehind文件中的Page_Load事件中增加以下代码:

'vb.net

Public Class Index

Inherits System.Web.UI.Page

Private Sub Page_Load(sender As Object, e As EventArgs) Handles MyBase.Load

Ajax.Utility.RegisterTypeForAjax(GetType(Index))

'...

end sub

'...

End Class

//C#

public class Index : System.Web.UI.Page{

private void Page_Load(object sender, EventArgs e){

Ajax.Utility.RegisterTypeForAjax(typeof(Index));

//...

}

//...

}

对RegisterTypeForAjax方法的调用在页面产生如下的javascript代码(另外一种选择,你也可以人工在页面上添加如下的javascript代码)

<script language="javascript" src="ajax/common.ashx"></script>

<script language="javascript"

src="ajax/NAMESPACE.PAGECLASS,ASSEMBLYNAME.ashx"></script>

上面这段代码的粗体部分NAMESPACE.PAGECLASS,ASSEMBLYNAME含义如下:

127>

NAMESPACE.PAGECLASS

463>

当前页面的命名空间和类

127>

ASSEMBLYNAME

463>

当前页面的程序集的名称

下面是在AjaxPlay项目中sample.aspx的示例输出:

650><%@ Page Inherits="AjaxPlay.Sample" Codebehind="sample.aspx.cs" ... %>

<html>

<head>

<script language="javascript" src="ajax/common.ashx"></script>

<script language="javascript"

src="ajax/AjaxPlay.Sample,AjaxPlay.ashx"></script>

</head>

<body>

<form id="Form1" method="post" runat="server">

...

</form>

</body>

</html>

你可以测试一下,人工通过浏览器将src path(通过查看源文件并copy)打开,一切都能正常的工作。如果输出了无意义的文本表示到目前为止是正确的,如果输出asp.net错误,则表示中间出现了错误。

即使你不了解HttpHandle的工作方式,也应该可以理解上面的描述。通过web.config,我们可以确保发送向ajax/*.ashx的请求由我们自定义的句柄来处理,很显然,两个脚本标记由自定义句柄处理。

编写服务端函数

现在我们编写服务器端函数,他们可以被客户端异步的调用。尽管现在还不能支持全部的返回类型,我们仍坚持服务器端添加功能。在codebehind文件的页面类里,添加下面的方法:

'VB.Net

<Ajax.AjaxMethod()> _

Public Function ServerSideAdd (byval firstNumber As Integer, byval secondNumber

As Integer) As Integer

Return firstNumber + secondNumber

End Function

//C#

[Ajax.AjaxMethod()]

public int ServerSideAdd(int firstNumber, int secondNumber)

{

return firstNumber + secondNumber;

}

注意,这个函数有Ajax.AjaxMethod()定制属性,属性服务会告知ajax封装类为此方法创建一个javascript代理,这样才能被客户端调用。

定制客户端调用

接下来在客户端用javascript调用函数。Ajax封装类会创建一个javascript函数,带有两个参数,名字是 类名.ServerSideAdd。作为最基本的功能,我们所需要作的只是调用这个方法并且传递参数:

<%@ Page Inherits="AjaxPlay.Sample" Codebehind="sample.aspx.cs" ... %>

<html>

<head>

<script language="javascript" src="ajax/common.ashx"></script>

<script language="javascript"

src="ajax/AjaxPlay.Sample,AjaxPlay.ashx"></script>

</head>

<body>

<form id="Form1" method="post" runat="server">

<script language="javascript">

var response = Sample.ServerSideAdd(100,99);

alert(response.value);

</script>

</form>

</body>

</html>

当然,我们不能把这么强大的功能仅仅用来通过alert来提醒浏览者,这就是为什么所有的客户端代理(如 类名.ServerSideAdd函数)同时带有一个额外的定制属性。这个属性是用来处理服务器响应的回调函数:

Sample.ServerSideAdd(100,99, ServerSideAdd_CallBack);

function ServerSideAdd_CallBack(response){

if (response.error != null){

alert(response.error);

return;

}

alert(response.value);

}

从上面的代码中可以看出,我们为ServerSideAdd函数增加了一个额外参数ServerSideAdd_CallBack,这个参数就是用来处理服务器端响应的客户端函数。这个callback函数接受一个带有四个关键属性的response对象:

79>

value

511>

服务器端函数执行的返回值(可能是一个字符串、自定义对象或者dataset)

79>

error

511>

如果发生错误,则返回错误信息.

79>

request

511>

原始的xmlHttpRequest请求

79>

context

511>

一个上下文对象

我们首先应该检查是否有错误发生,你可以通过在服务器端函数抛出异常来实现这个error属性。在上面这个例子中,我们简单的alert了一个值,就是value属性;request属性可以用来取得额外的信息(见下面的表格)

543>

如果你想了解更多的关于XmlHttpRequest的知识,可以查看下面的链接: http://www.quirksmode.org/blog/archives/2005/02/xmlhttp_linkdum.html

处理类型

返回一个复杂类型

Ajax可以支持除了我们上面ServerSideAdd函数返回的Int值以外很多类型。他可以直接支持integers, strings, double, booleans, DateTime, DataSets 和 DataTables,也支持简单的自定义类型和数组。其他的类型通过其ToString方式来返回字符串。

返回DataSet的工作就像真正的.net Dataset.给出一个返回DataSet的服务器端函数,我们可以通过下面的方法在客户端显示:

<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()]

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代理:

private void Page_Load(object sender, EventArgs e){

Utility.RegisterTypeForAjax(typeof(User));

}

在客户端我们可以通过这样的方式调用GetUser函数:

<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 and UserId)。

译者注:其他的类型只能由开发者通过在服务器端函数在返回值时自定义转换为ajax支持的类型来实现了,ajax推荐使用ToString方法。

其他工作方式

在其他类注册函数

在上面的例子及描述中,我们都是通过在页面的codebehind文件里完成函数的注册,但并不是说只能在页面的codebehide文件里完成注册,我们也可以在其他类中注册函数。回忆一下,Ajax封装类是通过在特定类里面查找那些有Ajax.AjaxMethod()属性的方法来完成工作的,这些类在客户端又通过两个script片断来完成返回值描述。使用Ajax.Utility.RegisterTypeForAjax,我们可以得到任何我们想得到类的详细内容。例如,下面的例子可以说明我们在其他类中使用服务器端函数是合法的:

Public Class AjaxFunctions

<Ajax.AjaxMethod()> _

Public Function Validate(username As String, password As String) As Boolean

'do something

'Return something

End Function

End Class

不过我们需要首先在调用页面注册这个代理类,类的名字不再是页面类,而是我们使用的这个类:

'Vb.Net

Private Sub Page_Load(sender As Object, e As EventArgs) Handles MyBase.Load

Ajax.Utility.RegisterTypeForAjax(GetType(AjaxFunctions))

'...

End Sub

//C#

private void Page_Load(object sender, EventArgs e){

Ajax.Utility.RegisterTypeForAjax(typeof(AjaxFunctions));

//...

}

记住,客户端调用使用这种格式的名字<ClassName>.<ServerSideFunctionName>。因此,如果上面的Serversideadd函数位于AjaxFunctions类,而不是页面类的话,客户端调用则变为:AjaxFunctions.ServerSideAdd(1,2)

代理是怎样工作的呢?

第二个script标签,如下面的示例

<script type="text/javascript" src="/cqyd/ajax/cqyd.SchemeSendWatch,cqyd.ashx"></script>

是由Ajax utility通过命名空间、类以及页面程序集自动生成的(当然也可以人工加入),从这一点我们可以想到Ajax.PageHandlerFactory是通过反射来取得有定制属性的函数的细节。很显然,Handler寻找带有AjaxMethod定制属性的函数,取得他们的特征(返回类型、名称、参数)并依据这些信息创建客户端代理。特别的,ajax创建一个与类型相同的JavaScript对象作为代理。

返回Unicode字符

Ajax.net可以从服务器端向客户端返回Unicode字符,为了做到这一点,在服务端函数返回时返回的值必须是Html编码的:

568>[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;

}

SessionState在服务端函数,你可能需要接受传送的session信息,为了做到这一点,必须要在想实现这个方式的服务端函数的Ajax.AjaxMethod属性上传递一个参数。

在查看ajax可以支持session的时候,我们先看看其他的特征。在下面这个例子中,我们有一个文档管理系统,当一个用户对文档进行编辑的时候会给这个文档加锁,其他用户需要等到这个文档可用时才能修改。不使用Ajax,用户需要不断等待刷新,因为不得不不断的去检查文档的状态是否为可用,这当然不是一个很好的方案。用ajax的session state支持,这就比较容易了。

我们首先写一个函数,这个函数通过遍历文档ID找到用户需要的文档,存储到session里,并返回没有占用的文档:

'Vb.Net

<Ajax.AjaxMethod(HttpSessionStateRequirement.Read)> _

Public Function DocumentReleased() As ArrayList

If HttpContext.Current.Session("DocumentsWaiting") Is Nothing Then

Return Nothing

End If

Dim readyDocuments As New ArrayList

Dim documents() As Integer = CType(HttpContext.Current.Session("DocumentsWaiting"), Integer())

For i As Integer = 0 To documents.Length - 1

Dim document As Document = document.GetDocumentById(documents(i))

If Not document Is Nothing AndAlso document.Status = DocumentStatus.Ready Then

readyDocuments.Add(document)

End If

Next

Return readyDocuments

End Function

//C#

[Ajax.AjaxMethod(HttpSessionStateRequirement.Read)]

public ArrayList DocumentReleased(){

if (HttpContext.Current.Session["DocumentsWaiting"] == null){

return null;

}

ArrayList readyDocuments = new ArrayList();

int[] documents = (int[])HttpContext.Current.Session["DocumentsWaiting"];

for (int i = 0; i < documents.Length; ++i){

Document document = Document.GetDocumentById(documents[i]);

if (document != null && document.Status == DocumentStatus.Ready){

readyDocuments.Add(document);

}

}

return readyDocuments;

}

}

我们在属性参数中指明了HttpSessionStateRequirement.Read(还可以是Write and ReadWrite)

下面写javascript函数来使用这个方法带来的结果:

<script language="javascript">

function DocumentsReady_CallBack(response){

if (response.error != null){

alert(response.error);

return;

}

if (response.value != null && response.value.length > 0){

var div = document.getElementById("status");

div.innerHTML = "The following documents are ready!<br />";

for (var i = 0; i < response.value.length; ++i){

div.innerHTML += "<a href=\"edit.aspx?documentId=" + response.value[i].DocumentId + "\">" + response.value[i].Name + "</a><br />";

}

}

setTimeout('page.DocumentReleased(DocumentsReady_CallBack)', 10000);

}

</script>

<body onload="setTimeout('Document.DocumentReleased(DocumentsReady_CallBack)', 10000);">

页面加载后每10秒钟向服务器函数请求一次。如果有返回,则call back函数检查response,并把最新的结果显示出来。

结论

Ajax技术可以给客户端提供丰富的客户体验,而ajax.net为您容易的实现这样强大的功能提供了可能。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有