封装类是通过在.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的最新版本。
如果你在安装引用时遇到了麻烦,可以参考这个链接的说明:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbcon/html/vbtskaddingremovingreferences.asp
为了使其可以工作,第一步必须做的是在web.config中安装设置封装包的HttpHandle,不去详细解释HttpHandle是如何工作的,我们只需要了解他们可以用来处理asp.net请求。
<configuration>
<system.web>
<httpHandlers>
<add verb="POST,GET" path="ajax/*.ashx" type="Ajax.PageHandlerFactory, Ajax" />
</httpHandlers>
...
<system.web>
</configuration>
上面的代码告诉asp.net把任何匹配到特定的路径(
现在我们准备好开始代码编写了。
'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="/blog/ajax/common.ashx"></script>
<script language="javascript"
src="ajax/
上面这段代码的粗体部分
NAMESPACE.PAGECLASS
当前页面的命名空间和类
ASSEMBLYNAME
当前页面的程序集的名称
下面是在AjaxPlay项目中sample.aspx的示例输出:
<%@ Page Inherits="
<html>
<head>
<script language="javascript" src="/blog/ajax/common.ashx"></script>
<script language="javascript"
src="ajax/
</head>
<body>
<form id="Form1" method="post" runat="server">
...
</form>
</body>
</html>
你可以测试一下,人工通过浏览器将src path(通过查看源文件并copy)打开,一切都能正常的工作。
即使你不了解HttpHandle的工作方式,也应该可以理解上面的描述。
现在我们编写服务器
'VB.Net
Public Function ServerSideAdd (byval firstNumber As Integer, byval secondNumber
As Integer) As Integer
Return firstNumber + secondNumber
End Function
//C#
public int ServerSideAdd(int firstNumber, int secondNumber)
{
return firstNumber + secondNumber;
}
注意,这个函数有Ajax.AjaxMethod()定制属性,属性服务会告知ajax封装类为此方法创建一个javascript代理,这样才能被客户端调用。
接下来在客户端用javascript调用函数。
<%@ Page Inherits="AjaxPlay.Sample" Codebehind="sample.aspx.cs" ... %>
<html>
<head>
<script language="javascript" src="/blog/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,这个参数就是用来处理服务器
value
服务器
error
如果发生错误,则返回错误信息.
request
原始的xmlHttpRequest请求
context
一个上下文对象
我们首先应该检查是否有错误发生,你可以通过在服务器
如果你想了解更多的关于XmlHttpRequest的知识,可以查看下面的链接: http://www.quirksmode.org/blog/archives/2005/02/xmlhttp_linkdum.html
Ajax可以支持除了我们上面ServerSideAdd函数返回的Int值以外很多类型。
返回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也可以支持自定义类,但是需要这个类是可以被序列化的。
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向服务器
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>
返回值同服务器
译者注:其他的类型只能由开发者通过在服务器
在上面的例子及描述中,我们都是通过在页面的codebehind文件里完成函数的注册,但并不是说只能在页面的codebehide文件里完成注册,我们也可以在其他类中注册函数。
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>。
第二个script标签,如下面的示例
<script type="text/javascript" src="/cqyd/ajax/cqyd.SchemeSendWatch,cqyd.ashx"></script>
是由Ajax utility通过命名空间、类以及页面程序集自动生成的(当然也可以人工加入),从这一点我们可以想到Ajax.PageHandlerFactory是通过反射来取得有定制属性的函数的细节。
Ajax.net可以从服务器
[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的时候,我们先看看其他的特征。
我们首先写一个函数,这个函数通过遍历文档ID找到用户需要的文档,存储到session里,并返回没有占用的文档:
'Vb.Net
<Ajax.AjaxMethod(
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(
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 >
页面加载后每10秒钟向服务器