MagicAjax

刚刚得知MagicAjax( http://www.magicajax.net/),他让你体验什么叫Easy AJAX,并支持.Net2.0。你无需对现有的webform方式开发有任何的改变,你只需配配web.config,拉拉控件就行了。本文不说用法,因为他实在太简单了,我在这里对他做一个分析,让大家了解他的工作方式。

从例子入手吧,一个button,一个label,点击button更新lable到当前时间。

设计器上的html:
< div  style ="width: 300px" >
    
< ajax:AjaxPanel  ID ="AjaxPanel1"  runat ="server" >
        
< asp:Button  ID ="Button1"  runat ="server"  OnClick ="Button1_Click"  Text ="Button"   />
        
< asp:Label  ID ="Label1"  runat ="server"  Text ="Label" ></ asp:Label ></ ajax:AjaxPanel >
</ div >

输出后的html:
< div >
< input  type ="hidden"  name ="__CONTROL_FINGERPRINTS_AjaxPanel1"  id ="__CONTROL_FINGERPRINTS_AjaxPanel1"  value =""   />
< input  type ="hidden"  name ="AjaxPanel1$RBS_Store"  id ="AjaxPanel1$RBS_Store"  value =""   />
< input  type ="hidden"  name ="__VIEWSTATE"  id ="__VIEWSTATE"  value ="/wEPDwUJNTg1NTY3MzczD2QWAgIDD2QWAgIBDw9kFgIeCEFqYXhDYWxsBQVhc3luY2RkWqu19ZXiwLYiiNPPAP+GKoHYdzs="   />
</ div >

< div  style ="width: 300px" >
    
< span  id ='AjaxPanel1$RBS_Holder' >< span  id ="Span1"  AjaxCall ="async" >
        
< span  id ="Button1$ajaxdest"  name ="__ajaxmark" >< input  type ="submit"  name ="Button1"  value ="Button"  id ="Submit1"   /></ span >
        
< span  id ="Label1$ajaxdest"  name ="__ajaxmark" >< span  id ="Span2" > Label </ span ></ span ></ span ></ span >
</ div >

< script  type ="text/javascript" >
<!--
var  RBS_Controls  =    new  Array(document.getElementById( " AjaxPanel1$RBS_Holder " ));
var  RBS_Controls_Store  =    new  Array(document.forms[ 0 ][ " AjaxPanel1$RBS_Store " ]);
//  -->
</ script >


MagicAjaxModule是一个IHttpModule拦截请求。主要处理在:
void Application_AcquireRequestState(object sender, EventArgs e)
·如果是普通Page,直接输出页面。
·如果请求是“Get”,直接输出页面。
·如果是ajax请求的话,由_request.Form["__AJAXCALL"]判断是否一个ajax请求,如果是则调用HttpContext.Current.Handler.ProcessRequest(HttpContext.Current)并更新相关状态,包括ViewState,最后Flush()页面。在这个过程当中,输出都是交给AjaxCallHelper完成,而这个help最后产生一个script,那么在客户端在接收到这个script,就直接执行:eval(responseText).比如例子中点击button后,最后产生的script是:
AJAXCbo.ExtendedSetHtmlOfElementScript( " <span id=/ " Label1/ " >2005-12-8 18:03:22</span> " , " Label1$ajaxdest " );

AJAXCbo.SetFieldScript(
" __CONTROL_FINGERPRINTS_AjaxPanel1 " , " C04A0FC;Button1#7DA27781;Label1#F84162CA " );

AJAXCbo.SetFieldScript(
" __VIEWSTATE " , " /wEPDwUKMTkwNzc1NDY4MQ9kFgICAw9kFgICAQ8PZBYCHghBamF4Q2FsbAUFYXN5bmMWAgIDDw8WAh4EVGV4dAUSMjAwNS0xMi04IDE4OjAzOjIyZGRk+HNmUx11Ztw2Z2CodiIhPxrEm4A= " );

'AJAX_LOADING_OK';
由此可以看出,点击button后,返回给客户端,客户端负责解释和执行这个script。
第一行:更新label里面的时间
第二行:更新panel的隐含字段
第三行:更新ViewState
第四行:一个标志,表示请求成功

客户端的js工作流程
1)首先,他把页面所有的ajaxPanel放在一个array里面:RBS_Controls,而每个panel都对应到另外一个array:RBS_Controls_Store 里面的各个panel的状态。
2)这时候大家注意到页面上这句js:
< script  language ='javascript' >
    
if  ( typeof (AJAXCbo)  ==  'undefined')
        alert(
" Unable to find script library '/AjaxCallObject.js'. Copy the file to the required location, or change the 'scriptPath' setting at magicAjax section of web.config. " );
    
else
        AJAXCbo.HookAjaxCall(
false , false , false );
</ script >
AjaxCallObject.prototype.HookAjaxCall = function(bPageIsStored, bUnloadStoredPage, bTracing)会hook几个事件:
window.onload,  window.onbeforeunload,  window.onunload,  document.forms[0].onsubmit(这是是重点)
3)点击panel里面的button发出一个submit,由于document.forms[0].onsubmit被hook了,他在这里引发:AJAXCbo.DoAjaxCall(target.name, "", cbType)并return false,就不会引发页面刷新。
4)在DoAjaxCall里面,一个for循环把form里面的内容序列化成字符串放在变量theData里面
5)调用XmlHttp工作:open->onreadystatechange(设置异步完成引发事件)->setRequestHeader->send
不管异步调用还是同步调用,最后都会引发:OnComplete事件,OnComplete就会调用eval(responseText)来执行服务段返回的script了。

AjaxPanel控件
控件主要render HTML,配合客户端的js工作。
·构造函数初始化控件的panel里面的XmlHttp请求方式。(同步/异步)
·void AddedControl(Control control, int index)把panel里面的服务端控件加到_addedControls这个集合里面,上面就是把Button1和Lable1加载。
·void OnLoad(EventArgs e)注册这个panel的隐含字段,就是上面的__CONTROL_FINGERPRINTS_AjaxPanel1。
·void OnPreRender(EventArgs e) :如果不是嵌套的panel加入隐含字段AjaxPanel1$RBS_Store和两个变量(RBS_Controls和RBS_Controls_Store)用处处理客户端AJAX调用。这里必要说明一下,这个隐含字段是用于类似ViewState的用途?
·void Render(HtmlTextWriter writer)把非嵌套的panel输出成<span>,就是上面的<span id='AjaxPanel1$RBS_Holder'> ,如果是嵌套的panel就只有顶层的panel有这个<span>。
·void RenderChildren(HtmlTextWriter writer)把panel里面的子控件输出,非服务端控件输出不变。如果是服务端控件就把这个控件放在一个<span>里面,并且id为:控件名称+$ajaxdest,name为:__ajaxmark。最后如果IsPageNoStoreMode是true则注册一个js,他会在客户端执行(AJAXCbo.SetFieldIfEmptyScript),把控件的状态放到__CONTROL_FINGERPRINTS_AjaxPanel1这个隐含字段。
< script  type ='text/javascript' >
AJAXCbo.SetFieldIfEmptyScript(
" __CONTROL_FINGERPRINTS_AjaxPanel1 " , " C04A0FC;Button1#7DA27781;Label1#31926D7E " );
</ script >
·void OnUnload(EventArgs e)IsPageNoStoreMode为true的话,会更新控件的更新控件的状态。


哈~好像写完了,最后给大家一个小秘诀。看看AjaxCallObject.js,当请求的时候,他会象GMail那样在右上脚出现一个Wait...的等待,很cool,你只要在这里做一个小更改,改CreateWaitElement那部分就能达到另外的效果。我这里把请求数据时,改成windows关机时,整个页面变灰的那种效果,类似的js如下:
< SCRIPT  type ="text/javascript" >
    
<!--
    
function  log_out()
    {
        ht1 
=  parent.frames.item( 0 ).document.getElementsByTagName( " html " );
        ht1[
0 ].style.filter  =   " progid:DXImageTransform.Microsoft.BasicImage(grayscale=1) " ;
        ht2 
=  document.getElementsByTagName( " html " );
        ht2[
0 ].style.filter  =   " progid:DXImageTransform.Microsoft.BasicImage(grayscale=1) " ;
        
if  (confirm('你是否确认注销?'))
        {
            
return   true ;
        }
        
else
        {
            ht1[
0 ].style.filter  =   "" ;
            ht2[
0 ].style.filter  =   "" ;
            
return   false ;
        }
    }
    
// -->
</ SCRIPT >

OK~希望本文对你有用,最后请大家斧正文中的错误。

Feedback

# re: 剖析MagicAjax  回复   

2005-12-08 22:16 by 纶巾客
好东西啊.

# re: 剖析MagicAjax  回复   

2005-12-08 22:19 by 听棠.NET
有空研究研究!!谢

# re: 剖析MagicAjax  回复   

2005-12-08 23:51 by 午夜寻欢
.net1.1的不知道支持不支持

# re: 剖析MagicAjax  回复   

2005-12-08 23:52 by 午夜寻欢
不好意思 刚回复就看到1.1的下载地址了!
han

# re: 剖析MagicAjax  回复   

2005-12-08 23:57 by 前进条幅
楼上,你真搞笑~

# re: 剖析MagicAjax  回复   

2005-12-09 02:42 by 绿叶
补充一下:改最后那个windows关机效果的时候,要这句在aspx文件上面。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" " http://www.w3c.org/TR/1999/REC-html401-19991224/loose.dtd" >

# re: 剖析MagicAjax  回复   

2005-12-09 08:27 by 一帆(老鼠粮仓之路)
MagicAjax确实方便,楼主的文章确实写的好,但是我碰到了两个问题,不知道楼主能够帮忙解决么?:
1,在AjaxPanel里面放个PlaceHolder,如果动态加载net自带的服务器控件没有什么问题,但是如果动态加载CuteEditor就会出现一些错误,不知道是MagicAjax的原因还是CuteEditor的原因?
2,当用客户端脚本调用服务器方法的时候,首先必须AJAXCbo.DoAjaxCall('','RunServerMethod');其中的RunServerMethod是要发送到服务器端的参数,服务器端方法再If (MagicAjaxContext.Current.IsAjaxCallForPage(this))
{
switch (MagicAjaxContext.Current.AjaxCallArgument)
{
case "RunServerMethod":
RunServerMethod();
break;
}
}

这个时候问题来了,因为是根据客户端发来的参数来确定调用什么服务器方法,如果发来的参数都是一段很长的html呢?而且不同的客户js发来不同的参数,这里怎么办?而且放到AjaxPanel里的任何服务器控件的服务器 方法所传递给服务器方法的参数是"";

# re: 剖析MagicAjax  回复   

2005-12-09 08:31 by 阿不
前几天也下载了,还没去看呢.不过能更新ViewState是真的很不错.

# re: 剖析MagicAjax  回复   

2005-12-09 08:51 by DDL
好东西啊。谢谢了

# re: 剖析MagicAjax  回复   

2005-12-09 09:59 by 狮子座小哲
叶子能详细说一下如何改代码和应用来实现注销那种效果么?谢谢了,我对这个挺好奇的

# re: 剖析MagicAjax  回复   

2005-12-09 10:04 by 狮子座小哲
还有个问题就是如何改变那个很cool的Wait...的等待显示位置,找了一会,没有头绪

# re: 剖析MagicAjax  回复   

2005-12-09 10:14 by 狮子座小哲
很cool的Wait...的等待显示位置我已经找到修改的位置了,在这个函数里改就可以

function MoveWaitElement()
{
if (!waitElement)
CreateWaitElement();

var width = document.body.clientWidth;
waitElement.style.top = document.body.scrollTop;
waitElement.style.left = width + document.body.offsetLeft - waitElement.offsetWidth;
}

# re: 剖析MagicAjax  回复   

2005-12-09 10:20 by 垃圾猪
看不去不错,下了看看先

# re: 剖析MagicAjax  回复   

2005-12-09 10:37 by Boler Guo
先标记一下,现在的项目用不到,说不定下一个项目就可以用上了!

# re: 剖析MagicAjax  回复   

2005-12-09 11:43 by 绿叶
出差两天,回来再和大家探讨,大家不要忘记把自己的使用心得发上来哦~

# re: 剖析MagicAjax  回复   

2005-12-09 13:12 by sharp-edge
哈哈,本来我也想写一篇的,被你抢先了,呵呵
写得不错,下一篇可以考虑分析一下服务端的源码

# re: 剖析MagicAjax  回复   

2005-12-09 13:30 by lovecherry
自己机器上能使用,传到服务器,分页的时候只出现loading没有反映了,怎么回事

# re: 剖析MagicAjax  回复   

2005-12-23 01:32 by 猪猪
请教:为什么我出现
Unable to find script library '/AjaxCallObject.js'
的错误?

我用.NET 1.1,VS.2003

看到出来的网页的源码里有一句
<script type="text/javascript" src="0.2.2.26746/AjaxCallObject.js.aspx"></script>

谁能点一下吗?
非常感谢!

# re: 剖析MagicAjax  回复   

2005-12-26 17:39 by 阿不
@ 猪猪
在web.config里加上
<httpModules>
<add name="MagicAjax" type="MagicAjax.MagicAjaxModule, MagicAjax" />
</httpModules>

# re: 剖析MagicAjax  回复   

2005-12-26 18:55 by onekey
2.0不支持中文是为什么?
我改Web.Config文件为gb2312了啊

# re: 剖析MagicAjax  回复   

2005-12-29 22:15 by onekey
还有一个问题就是 magicajax如何能够通过js去调用后台的方法?
像ajaxpro.net那样

# re: 剖析MagicAjax  回复   

2005-12-29 23:45 by 绿叶
@onekey
我看了看,好像没有对xmlHTTP的封装,你可以通过第三方的js达到目的,比如:Prototype

# re: 剖析MagicAjax  回复   

2005-12-30 13:23 by 阿不
@onekey
好像是啊,我昨天发现使用了MagicAjax后,会出现乱码的情况.这可不好啊.我在项目可是使用这东西的啊.应该算是一个BUG吧?

# re: 剖析MagicAjax  回复   

2006-01-09 11:33 by hai
我这现在下载不到了,一直连接不上啊
那位有的,请发一个支持.net1.1的给我!万分感谢!~~~~~~~~!

# re: 剖析MagicAjax  回复   

2006-01-09 11:35 by hai
我这现在下载不到了,一直连接不上啊
那位有的,请发一个支持.net1.1的给我!万分感谢!~~~~~~~~!
Mail:xch#inetcop.com.cn

# re: 剖析MagicAjax  回复   

2006-01-09 14:57 by 长江
我有一个问题,大概大家都没碰到。
就是:我是用GDI+做的一个条形统计图,因为做这个统计图不用任何控件,也就不存在“拉拉控件”的工作了,我是把统计图写在一个自定义的函数里,在页面加载的时候调用这个函数,统计图就出来了。现在我想实现的是: 每5秒自动刷新一次统计图。请问楼主绿叶和各位大峡怎样才能使用MagicAjax 来实现呢!??????

-------------------------------急呀,请各位帮忙解决啊!~~~~~~!------------------

# re: 剖析MagicAjax  回复   

2006-01-09 17:15 by 绿叶
@长江
magicajax的客户端没有对xmlhttp的封装,5秒刷新一次,你可以做个timer,然后用property1.31中里面有对xmlhttp的封装,用new Ajax.Request(....)来请求页面,并成功后set到相应的div里面,当然最简便的方法还有一个Ajax.Update(...)的,详细的文档你可以看:
http://www.sergiopereira.com/articles/prototype.js.html
如果要中文的文档这里:
https://compdoc2cn.dev.java.net/prototype/html/prototype.js.cn.html

# re: 剖析MagicAjax  回复   

2006-01-21 12:33 by @长江
用下面这种方式就可以了。
private void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// For automatic CallBack every 10 seconds.
MagicAjax.AjaxCallHelper.SetAjaxCallTimerInterval(10000);
}
UpdateChart();
}

# re: 剖析MagicAjax  回复   

2006-01-23 20:20 by 农民
挺好的,

# re: 剖析MagicAjax  回复   

2006-02-05 16:17 by AlexHe
asp.net 2.0中需要把AjaxCallObject.js用写字板转换为utf-8格式,便能使用中文了

# re: 剖析MagicAjax  回复   

2006-02-14 17:58 by 听棠.NET
楼主,我在MagicAjax里,想输入客户端脚本,但是使用Response.Write("<script>...</script>");不行的,不知道如何输入出我的客户端脚本呢?

# re: 剖析MagicAjax  回复   

2006-02-15 11:44 by 绿叶
尝试用:
AjaxCallHelper.WriteXXXX(...);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值