• 剖析MagicAjax



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

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

    设计器上的html:
    <div style=" 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=" 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~希望本文对你有用,最后请大家斧正文中的错误。
  • 相关阅读:
    Log4Net的使用之winform
    开源一个跨平台运行的服务插件
    定时管理器框架-Task.MainForm
    nginx+iis+redis+Task.MainForm构建分布式架构 之 (redis存储分布式共享的session及共享session运作流程)
    关于SQL查询效率,100w数据,查询只要1秒
    写的一般,从起源到具体算法-深度学习综述
    如何避免SHRINKDATABASE & SHRINKFILE 产生索引碎片(转载)
    在windows service中启动类型“Automatic” 和 “Automatic (Delayed start)” 有何不同?
    C# 对WinForm应用程序的App.config的加密
    SQL Server中怎么查看每个数据库的日志大小,以及怎么确定数据库的日志文件,怎么用语句收缩日志文件
  • 原文地址:https://www.cnblogs.com/wj/p/293271.html
Copyright © 2020-2023  润新知