【AjaxPro实现机制浅析一】AjaxPro内部为我们做什么工作?

先找个借口:好早就想分析下AjaxPro的代码实现机制了,一直苦于没时间,现在嘛总算有那么丁点了,开篇了,慢慢分析……

以一个最简单的例子开始:
点击一个客户端button,触发一个javascript函数,执行一个只有一个string参数的服务端方法,返回一个处理过的string,处理方法是将传入的string变成“Hi”+string +“!”;够简单了,为了是不希望罗嗦的代码影响简单的分析;
所有代码如下:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Test.aspx.cs" Inherits="Test" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    
<title>无标题页</title>
    
<script type="text/javascript">
     
    
function doTest() 
    
{
        AJAXDemo.Examples.Test.TestMethod.GetTest(
"AjaxPro",doTest_callback);
    }


    
function doTest_callback(res) {
        alert(res.value);
    }

    
    
</script>
</head>
<body>
    
<form id="form1" runat="server">
    
<div>
        
<input id="Button1" type="button" onclick="doTest()" value="测试"/></div>
    
</form>
</body>
</html>

Test.aspx.cs
public partial class Test : System.Web.UI.Page
{
    
protected void Page_Load(object sender, EventArgs e)
    
{
        Utility.RegisterTypeForAjax(
typeof(AJAXDemo.Examples.Test.TestMethod));
    }

}

AJAXDemo.Examples.Test
using System;
using AjaxPro;

namespace AJAXDemo.Examples.Test
{
    
public class TestMethod
    
{
        
public TestMethod()
        
{}

        [AjaxMethod]
        
public string GetTest(string testText)
        
{
            
return "Hi," + testText + "!";
        }

    }

}

1.首先我们看AjaxPro在页面上给我们生成了什么?
Test[1]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head><title>
    无标题页
</title>
    
<script type="text/javascript">
     
    
function doTest() 
    
{
        AJAXDemo.Examples.Test.TestMethod.GetTest(
"AjaxPro",doTest_callback);
    }


    
function doTest_callback(res) {
        alert(res.value);
    }

    
    
</script>
</head>
<body>
    
<form name="form1" method="post" action="Test.aspx" id="form1">
<div>
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUJNzgzNDMwNTMzZGRFekXifzWDNb+qFWPbJumdlZh/dQ==" />
</div>

<script type="text/javascript" src="/AJAXDemo.2/ajaxpro/prototype.ashx"></script>
<script type="text/javascript" src="/AJAXDemo.2/ajaxpro/core.ashx"></script>
<script type="text/javascript" src="/AJAXDemo.2/ajaxpro/converter.ashx"></script>
<script type="text/javascript" src="/AJAXDemo.2/ajaxpro/AJAXDemo.Examples.Test.TestMethod,App_Code.un7rskvh.ashx"></script>

    
<div>
        
<input id="Button1" type="button" onclick="doTest()" value="测试"/></div>
    
</form>
</body>
</html>

一定要注意这几行
<script type="text/javascript" src="/AJAXDemo.2/ajaxpro/prototype.ashx"></script>
<script type="text/javascript" src="/AJAXDemo.2/ajaxpro/core.ashx"></script>
<script type="text/javascript" src="/AJAXDemo.2/ajaxpro/converter.ashx"></script>
<script type="text/javascript" src="/AJAXDemo.2/ajaxpro/AJAXDemo.Examples.Test.TestMethod,App_Code.urx4hqkg.ashx"></script>

通过使用http://localhost:3578/AJAXDemo.2/ajaxpro/prototype.ashxhttp://localhost:3578/AJAXDemo.2/ajaxpro/core.ashx不难发现,其中前面两个是源代码中带的两个js文件(core.js和prototype.js)转化出来的,基本内容也跟原来的文件一样,而converter.ashx和AJAXDemo.Examples.Test.TestMethod,App_Code.urx4hqkg.ashx里面有什么呢?看下面:
AJAXDemo.Examples.Test.TestMethod,App_Code.urx4hqkg.ashx
addNamespace("AJAXDemo.Examples.Test");
AJAXDemo.Examples.Test.TestMethod_class 
= Class.create();
AJAXDemo.Examples.Test.TestMethod_class.prototype 
= (new AjaxPro.AjaxClass()).extend({
    GetTest: 
function(testText) {
        
return this.invoke("GetTest"{"testText":testText}this.GetTest.getArguments().slice(1));
    }
,
    initialize: 
function() {
        
this.url = '/AJAXDemo.2/ajaxpro/AJAXDemo.Examples.Test.TestMethod,App_Code.un7rskvh.ashx';
    }

}
);
AJAXDemo.Examples.Test.TestMethod 
= new AJAXDemo.Examples.Test.TestMethod_class();

converter.ashx

 

addNamespace("Ajax.Web");

Ajax.Web.NameValueCollection 
= function()
{
    
this.__type = "System.Collections.Specialized.NameValueCollection";

    
this.add = function(key, value) {
        
if(this[key] == null{
            
this[key] = value;
        }

    }

    
    
this.getKeys = function() {
        
var keys = [];
        
        
for(key in this)
            
if(typeof this[key] != "function")
                keys.push(key);
            
        
return keys;
    }

    
    
this.getValue = function(key) {
        
return this[key];
    }

    
    
this.toJSON = function() {
        
var o = this;
        o.toJSON 
= null;
        
delete o.toJSON;
        
return AjaxPro.toJSON(o);
    }

}





addNamespace(
"Ajax.Web");

Ajax.Web.DataTable 
= function(columns, rows) {

    
this.__type = "System.Data.DataTable, System.Data";
    
this.Columns = new Array();
    
this.Rows = new Array();

    
this.addColumn = function(name, type) {
        
var c = new Object();
        c.Name 
= name;
        c.__type 
= type;
        
        
this.Columns.push(c);
    }


    
this.toJSON = function() {
        
var dt = new Object();

        dt.Columns 
= [];
        
for(var i=0; i<this.Columns.length; i++)
            dt.Columns.push([
this.Columns[i].Name, this.Columns[i].__type]);

        dt.Rows 
= [];
        
for(var i=0; i<this.Rows.length; i++{
            
var row = [];
            
for(var j=0; j<this.Columns.length; j++)
                row.push(
this.Rows[i][this.Columns[j].Name]);
            dt.Rows.push(row);
        }


        
return AjaxPro.toJSON(dt);
    }


    
this.addRow = function(row) {
        
this.Rows.push(row);
    }


    
if(columns != null{
        
for(var i=0; i<columns.length; i++{
            
this.addColumn(columns[i][0], columns[i][1]);
        }

    }


    
if(rows != null{
        
for(var i=0; i<rows.length; i++{
            
var row = new Object();
            
for(var c=0; c<this.Columns.length && c<rows[i].length; c++{
                row[
this.Columns[c].Name] = rows[i][c];
            }

            
this.addRow(row);
        }

    }

}



addNamespace(
"Ajax.Web");

Ajax.Web.DataSet 
= function(tables) {
    
this.__type = "System.Data.DataSet, System.Data";
    
this.Tables = new Array();

    
this.addTable = function(table) {
        
this.Tables.push(table);
    }


    
if(tables != null{
        
for(var i=0; i<tables.length; i++{
            
this.addTable(tables[i]);
        }

    }

}








function Person(id) {
    
this.FirstName = "";
    
this.FamilyName = "";
    
this.Age = 0;
    
this.ID = id;
    
this.__type = 'AJAXDemo.Examples.Classes.Person, App_Code.un7rskvh, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null';
}


Person.prototype.get_FullName 
= function() {
    
return this.FirstName + " " + this.FamilyName;
}


Person.prototype.toJSON 
= function() {
    
var o = new Object();

    o.firstName 
= this.FirstName;
    o.familyName 
= this.FamilyName;
    o.age 
= this.Age;
    o.id 
= this.ID;

    
return AjaxPro.toJSON(o);
}


Person.prototype.save 
= function() {
    
return Person.save(this);
}


Person.save 
= function(p) {
    
var ps = new PersonSaver();
    
return ps.savePerson(p);    // synchronous call
}


var PersonSaver = Class.create();
PersonSaver.prototype 
= (new AjaxPro.Request()).extend({
    savePerson: 
function(p) {
        
return this.invoke("SavePerson"{"p":p}).value;
    }
,
    initialize: 
function() {
        
this.url = "ajaxpro/AJAXDemo.Examples.Classes.Person, App_Code.un7rskvh, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null.ashx";
    }

}
)


正因为是有了上面四个ashx文件我们的
function doTest() 
{
    AJAXDemo.Examples.Test.TestMethod.GetTest(
"AjaxPro",doTest_callback);
}
才得以异步执行,这些ashx文件又是怎么生成到页面上的,那得归功于web.config的相关配置和下面这句代码:
Utility.RegisterTypeForAjax(typeof(AJAXDemo.Examples.Test.TestMethod));

至于Utility.RegisterTypeForAjax方法产生的一序列动作我将在后文中继续说明,有兴趣的可以自己跟踪下这些代码的执行。
[未完待续]

posted @ 2006-03-16 17:42  冰戈  阅读(7932)  评论(21编辑  收藏  举报