初稿地址:http://www.codeproject.com/KB/ajax/aspnetajaxtips.aspx
[原稿源码下载]

[翻译]ASP.NET AJAX之内部揭秘

原稿发表日期:二零零七.12.22
作者:About Omar Al
Zabir

翻译:webabcd
审校:Tony Qu 

介绍
微软日前发布了ASP.NET AJAX的Beta
2版。就算它是八个格外强劲的框架,可是当您在web
2.0的社会风气中要费用1个真的的AJAX
web站点的话,就会赶上不少标题,而且你大概找不到其余相关文书档案。本文中,笔者将介绍一些在支付Pageflakes中所学习到的高档经验。大家将会看出ASP.NET
AJAX一些功能的利弊,如批调用(Batch
Call),调用超时,浏览器调用拥堵难点,ASP.NET 2.0中web
service响应缓存的bug等等。

正文最终更新:二零零五年11月六日,针对ASP.NET AJAX
奥迪Q3C更新(译注:适用于ASP.NET AJAX v1.0)

何以要动用ASP.NET AJAX
一些人在看到Pageflakes的时候,首先问小编的难题就是“为啥不使用Protopage可能Dojo库?而是Atlas?”微软的Atlas(已重命名为ASP.NET
AJAX)是三个相当有前景的AJAX框架。微软为了这几个框架做了好多大力,制作了大气可选取的机件,那样可以减掉你的耗时,那样的话,只要很少的工作量即可让您的web应用程序有八个圆满的界面。它与ASP.NET融合为一,并且包容ASP.NET的Membership和Profile。AJAX
Control
Toolkit
项目蕴涵了贰14个扩充(译注:今后有35个),你可以把它们拖拽到页面上,然后经过设置某个属性就能够发生非常酷的效用。看看那一个例子你就会明白ASP.NET
AJAX给大家带来了何等强大的效用。

在大家早期开发Pageflakes的时候,Atlas还处在幼儿阶段。大家只好选拔page
method和Web
Service方法来调用Atlas的特色。大家只可以开发大家本身的拖拽、组件构造、弹出、伸缩/展开等天性。不过未来,Atlas提供了具备这几个功能,所以能够大大节省大家的付出时间。最令人惊讶的是Atlas提供了web
service代理的风味。你能够钦赐<script>标签到一个.asmx文本,然后你会拿到三个JavaScript类,它会依据web
service的概念被科学的浮动。那使得添加或移除2个web
service变得万分容易,而且你在web
service中添加或移除方法都不要求客户端作任何变动。Atlas也提供了不可胜计基于AJAX调用的控件,并且提供了在JavaScript中捕获丰硕万分音信的性状。服务器端的格外能够被准确无误的抛给客户端的JavaScript代码,你能够捕获它们并格式化这一个错误音讯,然后突显给用户。Atlas与ASP.NET
2.0构成起来工作得相当精粹,完全化解了组合难题。你不须求操心page
method和web
service的认证和授权难题,所以可以大大裁减你的客户端代码的开发量(当然,也便是因为这么,Atlas运转时也变得要命了不起),相对于任何的AJAX框架来说,你可以把更加多的活力放到自个儿的代码开发上来。

Atlas近来的本子能够与ASP.NET的Membership、Profile完美的咬合,为你提供了在JavaScript中登录和裁撤的风味,而毫不发postback给服务器,你也得以直接从JavaScript中读取和写入Profile。当你在web应用程序中运用Membership和Profile的时候,那将变得格外简单,例如大家做的Pageflakes

在Atlas的早些版本中,没有运用HTTP GET调用的主意。全数的调用都以HTTP
POST,所以调用的代价是可怜大的。近年来后,你能够说,哪个调用是HTTP
GET的(而哪些不是)。一旦您利用了HTTP
GET,你就足以采纳HTTP响应缓存特性,小编将便捷介绍这一表征。

批调用并不一定快
ASP.NET
AJAX的CTP版本(此前的本子)里有3个表征,正是允许在一个呼吁里含有多个请求。它工作时你不会注意到任何业务,而且也不需求写任何特殊的代码。一旦你利用了批调用特色,那么在贰次批调用时期,当中具有的web
service调用都会被实施,所以它将压缩回发时间和总响应时间。

实际上的响应时间恐怕缩减了,可是大家感觉到到的延期却变长了。假诺有3个web
service被批量调用,那么首先个调用不会首先完毕,而是兼具一个调用会在同样的大运成功。纵然你的每2个web
service调用完了后都更新UI的话,将不会一步一步更新,而是在享有调用一起完成后再一同更新UI。结果,你不会看到UI被高效翻新,而是在UI被更新在此以前有三个长日子的延期。假如说调用中的任何二个(比如首个调用)下载了汪洋数码,那么在拥有的三个调用完毕以前用户不会师到其余变动。所以首先个调用的履行时间差不离接近二个调用的总执行时间。固然裁减了实在的总共拍卖时间,然则会感觉有更长的延迟。当各样调用都只传输少量数码的时候批调用是可怜好的,那样,二个袖珍调用就会在1回回发中推行完。

让我们看看三个调用是什么一个两个被成功的,那将申明那个调用实际上是哪些被实施的。
图片 1

第3个调用到达服务端的光阴要比第三个调用长,因为第3个调用吃光了带宽。同样的因由,下载也就会花越多的年华。浏览器同时开辟了多个再而三到劳动器端的总是,所以在同目前间,只可以处理四个调用。一旦第3个调用或第1个调用实现后,首个调用才能被处理。

当二个web service在1遍呼吁中被批调用的时候:
图片 2

此间一起下载时间将会具有压缩(若是IIS的削减功用启用的话),并且只需3次网络响应。全数的二个调用2遍被发往到服务端后整个实践,组合而成的多个调用的响应是在三遍调用中下载。不过对于用户来讲,他们会觉得速度变慢了,因为UI的翻新爆发在颇具批调用完了之后。这么些批调用完了的总时间总是要善用八个调用的。并且,假设你有恢宏的二个又一个的UI更新,IE将会结霜一段时间,那将给用户带来1个糟糕的心得。一些时候,时间较长的UI更新会促成浏览器出现“白屏”,可是FireFox和Opera不会有此问题。

批调用也是有局部独到之处的。就算您的IIS启用了gzip压缩功用的话,将对全部结出开始展览削减而不是个别收缩每一个结果,那么总下载时间长度就会不难单独调用的下载时间长度。所以,常常批调用都是部分小型调用的话会比较好。可是一旦调用会发送恐怕重返较大数额以来,比如20KB,那么最好就别使用批调用了。批调用还有另八个标题,比如说前三个调用相当的小,第三个调用非常大,假使那二个调用被批调用的话,那么前三个小的调用就要延期很短日子,因为第二个十分的大。

倒霉的调用会使好的调用超时
假诺有三个HTTP调用不知怎么执行了十分长的时日,那么那四个糟糕的调用也将会使好的调用超时,同时那七个调用会进入队列。那里就有三个例证:

图片 3function TestTimeout()
图片 4图片 5图片 6{
图片 7    debug.trace(“–Start–“);
图片 8    TestService.set_defaultFailedCallback( 
图片 9            function(result, userContext, methodName)
图片 10图片 11    图片 12{
图片 13        var timedOut = result.get_timedOut();
图片 14        if( timedOut )
图片 15            debug.trace( “Timedout: ” + methodName );
图片 16        else
图片 17            debug.trace( “Error: ” + methodName );
图片 18    });
图片 19    TestService.set_defaultSucceededCallback( function(result)
图片 20图片 21    图片 22{
图片 23        debug.trace( result );
图片 24    });
图片 25    
图片 26    TestService.set_timeout(5000);
图片 27    TestService.HelloWorld(“Call 1”);
图片 28    TestService.Timeout(“Call 2”);
图片 29    TestService.Timeout(“Call 3”);
图片 30    TestService.HelloWorld(“Call 4”);
图片 31    TestService.HelloWorld(“Call 5”);
图片 32    TestService.HelloWorld(null); // 那句将促成错误
图片 33}

服务端的web service也万分简单:

图片 34[WebService(Namespace = “http://tempuri.org/")\]
图片 35[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
图片 36[ScriptService]
图片 37图片 38public class TestService : System.Web.Services.WebService 图片 39{
图片 40
图片 41图片 42    public TestService () 图片 43{
图片 44
图片 45        // 假使使用陈设的机件,请撤废注释以下行  
图片 46        // InitializeComponent(); 
图片 47    }
图片 48
图片 49    [WebMethod][ScriptMethod(UseHttpGet=true)]
图片 50图片 51    public string HelloWorld(string param) 图片 52{
图片 53        Thread.Sleep(1000);
图片 54        return param;
图片 55    }
图片 56    
图片 57    [WebMethod][ScriptMethod(UseHttpGet=true)]
图片 58图片 59    public string Timeout(string param) 图片 60{
图片 61        Thread.Sleep(10000);
图片 62        return param;
图片 63    }
图片 64}

自作者调用了服务端的名为“Timeout”的法子,它不会做其余工作,而只是等待一个较长的时日以使调用超时。之后,作者再调用一个不会晚点的主意。可是你猜猜输出的是哪些:
图片 65

唯有第三个调用成功了。所以,任曾几何时候假设浏览器的三个一而再都处于拥堵情形以来,那么您期望的任何调用也都将会晚点。

在Pageflakes的营业中,大家曾经大概每日都从客户端得到400个到600个超时错误报告,大家从未发现那是怎么产生的。起始,大家嫌疑是互连网连接过慢造成的,不过不恐怕那样多的用户都发生那种气象。后来,大家估算是主机提供商的网络现身了难题。大家做了大批量的互连网析去发现难点是或不是是出现在网络上,不过大家从未发现此外至极。大家选取了SQL
Profiler去搜寻是不是是长日子运作的询问导致了ASP.NET请求执行时的晚点。但是不幸,大家最终发现的是,当先八分之四超时错误出现的场所都以先有一对坏的调用,然后好的调用也过期了。所以大家修改了Atlas运营时,引进了活动重试的功效,难点终于完全消灭了。然则,自动重试须求对ASP.NET
AJAX框架的Javascript做一次“灵魂妇科手术”,这么些方法会要求各样调用在逾期后都重试1次。为了贯彻它,大家需求截获全体web
method调用并且在onFailure回调函数中作个钩,若是退步的原故是晚点,onFailure将再一次调用相同的web
method

另二个急需关注的觉察是当大家外出旅行感到辛勤时,想透过酒馆或飞机场的有线互联网连接到互连网访问Pageflakes的时候,第二回访问总是不成事,并且具有的web
service调用在第壹遍尝试中一而再战败。直到大家刷新在此之前都不会做事。那也是大家要促成web
service调用当下自动重试的另八个重中之重缘由,它恰恰能够缓解那一个题材。

此地作者会告诉您怎么做。Sys$Net$WebServiceProxy$invoke函数是承受处理全数web
service调用的。所以,大家供给经过1个自定义onFailure回调函数来替换这么些函数。只要有不当可能逾期就会激起那些自定义回调函数。所以,当有逾期产生的时候,就会再一次调用那一个函数,重试就会时有发生。

图片 66Sys.Net.WebServiceProxy.retryOnFailure = 
图片 67    function(result, userContext, methodName, retryParams, onFailure)
图片 68图片 69图片 70{
图片 71    if( result.get_timedOut() )
图片 72图片 73    图片 74{
图片 75        if( typeof retryParams != “undefined” )
图片 76图片 77        图片 78{
图片 79            debug.trace(“Retry: ” + methodName);
图片 80            Sys.Net.WebServiceProxy.original_invoke.apply(this, retryParams );
图片 81        }
图片 82        else
图片 83图片 84        图片 85{
图片 86            if( onFailure ) onFailure(result, userContext, methodName);
图片 87        }
图片 88    }
图片 89    else
图片 90图片 91    图片 92{
图片 93        if( onFailure ) onFailure(result, userContext, methodName);
图片 94    }
图片 95}
图片 96
图片 97Sys.Net.WebServiceProxy.original_invoke = Sys.Net.WebServiceProxy.invoke;
图片 98Sys.Net.WebServiceProxy.invoke = 
图片 99    function Sys$Net$WebServiceProxy$invoke(servicePath, methodName, useGet, 
图片 100        params, onSuccess, onFailure, userContext, timeout)
图片 101图片 102图片 103{   
图片 104    var retryParams = [ servicePath, methodName, useGet, params, 
图片 105        onSuccess, onFailure, userContext, timeout ];
图片 106    
图片 107    // 开头调用退步
图片 108    // 处理自动重试
图片 109    var newOnFailure = Function.createDelegate( this, 
图片 110        function(result, userContext, methodName) 
图片 111图片 112        图片 113
图片 114            Sys.Net.WebServiceProxy.retryOnFailure(result, userContext, 
图片 115                methodName, retryParams, onFailure); 
图片 116        } );
图片 117        
图片 118    Sys.Net.WebServiceProxy.original_invoke(servicePath, methodName, useGet, 
图片 119        params, onSuccess, newOnFailure, userContext, timeout);
图片 120}

运作的时候,它将把种种超时调用都重试2遍
图片 121

那边你能够看看第②个办法成功了,全体其余超时的调用都会被重试。而且你也会看出重试3回后的调用都事业有成了。发生那种景色是因为在重试中服务端的主意不会做超时处理。所以,那表明了大家的兑现方式是没错的。

浏览器只允许同暂时间内有八个调用,此时不会实施此外任何命令
浏览器在同一时半刻间内只好对1个域名处理三个冒出的AJAX调用。要是你有多少个AJAX调用,那么浏览器首先将会处理五个,然后等内部一个到位后,再处理另多少个调用,直到剩下的伍个调用都被成功。其它,你不要期待调用的推行各样会与您处理调用的一一相同,那是为啥呢?
图片 122

正如您所见,调用3索要下载相比较大的数据,所以它所需的岁月就会比调用5要长,事实上,调用5会在调用3之前实施完。

从而,在HTTP的世界里,这一个都以不足预言的。

当队列里有多于多少个调用的时候浏览器将不会响应
品尝那样做,在第②次访问时打开任何三个加载了汪洋RAV4SS的页(如Pageflakes,
Netvibes,
Protopage),在加载时期,你能够尝试着单击二个链接到另一个站点依旧试着直接待上访问另三个站点,那么您就会意识浏览器不会有其余响应。直到浏览器里具有队列的AJAX调用都做到之后,浏览器才能承受另八个移动。那是IE的一个相比不好的地方,可是Firefox和Opera就不会有此难点。

以此题材是,当您有恢宏的AJAX调用的时候,浏览器会将有所的调用放到七个种类里,在同暂且间内只举办个中的多少个。所以,借使你单击了某些链接或许转载另三个站点,那么浏览器必须等待在取得另一个调用此前正在进行的调用实现之后才会去处理。消除这几个难题的办法就是谨防浏览器在同权且间内有多于三个的调用在队列里。大家须要保险3个要好的体系,然后从大家的行列里将三个二个调用的发到浏览器的队列中。

那么些消除方案是很棒,它可防止患调用间的争辨:

图片 123图片 124var GlobalCallQueue = 图片 125{
图片 126    _callQueue : [],    // 保存web method的调用列表
图片 127    _callInProgress : 0,    // 浏览器方今拍卖的web method的编号
图片 128    _maxConcurrentCall : 2, // 同近来间内推行调用的最大数
图片 129    _delayBetweenCalls : 50, // 调用执行之间的延迟
图片 130    call : function(servicePath, methodName, useGet, 
图片 131        params, onSuccess, onFailure, userContext, timeout)
图片 132图片 133    图片 134{
图片 135        var queuedCall = new QueuedCall(servicePath, methodName, useGet, 
图片 136            params, onSuccess, onFailure, userContext, timeout);
图片 137
图片 138        Array.add(GlobalCallQueue._callQueue,queuedCall);
图片 139        GlobalCallQueue.run();
图片 140    },
图片 141    run : function()
图片 142图片 143    图片 144{
图片 145        /// 从队列里推行多个调用
图片 146        
图片 147        if( 0 == GlobalCallQueue._callQueue.length ) return;
图片 148        if( GlobalCallQueue._callInProgress < 
图片 149            GlobalCallQueue._maxConcurrentCall )
图片 150图片 151        图片 152{
图片 153            GlobalCallQueue._callInProgress ++;
图片 154            // 获得第3个调用队列
图片 155            var queuedCall = GlobalCallQueue._callQueue[0];
图片 156            Array.removeAt( GlobalCallQueue._callQueue, 0 );
图片 157            
图片 158            // 调用web method
图片 159            queuedCall.execute();
图片 160        }
图片 161        else
图片 162图片 163        图片 164{
图片 165            // 达到最大并发数,不可能运作另一个调用
图片 166    // 处理中的webservice method
图片 167        }
图片 168    },
图片 169    callComplete : function()
图片 170图片 171    图片 172{
图片 173        GlobalCallQueue._callInProgress –;
图片 174        GlobalCallQueue.run();
图片 175    }
图片 176};
图片 177
图片 178QueuedCall = function( servicePath, methodName, useGet, params, 
图片 179    onSuccess, onFailure, userContext, timeout )
图片 180图片 181图片 182{
图片 183    this._servicePath = servicePath;
图片 184    this._methodName = methodName;
图片 185    this._useGet = useGet;
图片 186    this._params = params;
图片 187    
图片 188    this._onSuccess = onSuccess;
图片 189    this._onFailure = onFailure;
图片 190    this._userContext = userContext;
图片 191    this._timeout = timeout;
图片 192}
图片 193
图片 194QueuedCall.prototype = 
图片 195图片 196图片 197{
图片 198    execute : function()
图片 199图片 200    图片 201{
图片 202        Sys.Net.WebServiceProxy.original_invoke( 
图片 203            this._servicePath, this._methodName, this._useGet, this._params,  
图片 204            Function.createDelegate(this, this.onSuccess), // 调用处理完毕
图片 205            Function.createDelegate(this, this.onFailure), // 调用处理实现
图片 206            this._userContext, this._timeout );
图片 207    },
图片 208    onSuccess : function(result, userContext, methodName)
图片 209图片 210    图片 211{
图片 212        this._onSuccess(result, userContext, methodName);
图片 213        GlobalCallQueue.callComplete();            
图片 214    },        
图片 215    onFailure : function(result, userContext, methodName)
图片 216图片 217    图片 218{
图片 219        this._onFailure(result, userContext, methodName);
图片 220        GlobalCallQueue.callComplete();            
图片 221    }        
图片 222};

QueueCall封装了1个web
method调用,它抱有真正web服务调用的具有参数,并且重写了onSuccess和onFailure回调函数。大家想通晓当2个调用完毕大概退步了的时候,怎样从咱们的连串里调出另2个调用。GlobalCallQueue保存了web服务调用的列表。无论曾几何时,当二个web
method被调用时,我们先要对GlobalCallQueue中的调用实行排队,并从我们团结的行列里多个1个的施行调用。那样就能够保障浏览器在平等的日子里不会有多于多个的调用,所以浏览器就不会甘休响应。

为了确定保障加利亚队列是基于调用的,大家需求像在此以前那样再一次重写ASP.NET AJAX的web
method

图片 223Sys.Net.WebServiceProxy.original_invoke = Sys.Net.WebServiceProxy.invoke;
图片 224Sys.Net.WebServiceProxy.invoke = 
图片 225    function Sys$Net$WebServiceProxy$invoke(servicePath, methodName, 
图片 226        useGet, params, onSuccess, onFailure, userContext, timeout)
图片 227图片 228图片 229{   
图片 230    GlobalCallQueue.call(servicePath, methodName, useGet, params, 
图片 231        onSuccess, onFailure, userContext, timeout);
图片 232}

在浏览器中缓存web服务响应得以显然节省带宽
浏览器能够在用户的硬盘里缓存图片、JavaScript、CSS文件,倘诺XML
HTTP调用是四个HTTP
GET的话也是足以缓存的。这一个缓存是基于U宝马X3L的。倘使是一模一样U兰德酷路泽L,且保存在同一个计算机里,那么数量将从缓存里加载,而不会向服务器再度呼吁。基本上,浏览器能够缓存任何HTTP
GET请求并且再次回到基于U宝马X5L的被缓存数据。假设你把1个XML HTTP调用作为HTTP
Get格局的话,那么服务端将回来一些与众差异的头音信,用于公告浏览器对相应做缓存,之后再也调用相同的剧情,结果就会马上从缓存中被再次回到,从而减弱了互联网传输延迟和下载时间。

在Pageflakes中,大家对用户的气象做了缓存,所以当用户再度走访的时候会从浏览器的缓存里立即获得缓存数据,而不用经过服务端。由此第一回加载时间会变得拾壹分快。大家也缓存了用户的有些行为所发生的结果。当用户再度做一样行为时,缓存结果就会及时从用户的地点缓存中加载,从而减少了互连网传输时间。用户会体会到一个非常快加载和高响应的站点,获得速度会有引人侧目增强。

以此格局就是处理Atlas web service调用时要利用HTTP
GET格局,并且要赶回一些醒目标HTTP头音信告诉浏览器具体要缓存多久。如若在响应时期你回去了2个“Expires”头音讯,那么浏览器就会缓存那些XML
HTTP结果。那里你需求重临四个头新闻去通告浏览器缓存结果。

图片 233HTTP/1.1 200 OK 
图片 234Expires: Fri, 1 Jan 2030 
图片 235Cache-Control: public

该消息将通知浏览器要缓存结果直到2030年八月25日。在你处理具有同等参数的同3个XML
HTTP调用的时候,就将从总括机的缓存中加载数据,而不会通过服务端。那里还有越多的支配缓存的高等方法。例如,有二个头新闻公告浏览器缓存60秒,那么浏览器要在60秒未来才能接触到服务端并拿走新的结果。当60秒后浏览器本地缓存过期的时候,它也会制止从代理服务器端获得已缓存的响应。

图片 236HTTP/1.1 200 OK 
图片 237Cache-Control: private, must-revalidate, proxy-revalidate, max-age=60

让大家来尝试着在3个ASP.NET web service方法中发生这么的头新闻:

图片 238[WebMethod][ScriptMethod(UseHttpGet=true)]
图片 239public string CachedGet()
图片 240图片 241图片 242{
图片 243    TimeSpan cacheDuration = TimeSpan.FromMinutes(1);
图片 244    Context.Response.Cache.SetCacheability(HttpCacheability.Public);
图片 245    Context.Response.Cache.SetExpires(DateTime.Now.Add(cacheDuration));
图片 246    Context.Response.Cache.SetMaxAge(cacheDuration);
图片 247    Context.Response.Cache.AppendCacheExtension(
图片 248           “must-revalidate, proxy-revalidate”);
图片 249
图片 250    return DateTime.Now.ToString();
图片 251}

结果就是下列头新闻:
图片 252

“Expires”头消息被正确的安装。可是难点时有发生在“Cache-Control”,它显得了“max-age”的值被设置成零,那将阻止浏览器从别的缓存中读取数据。借使您确实想禁止使用缓存,当然要发送那样一条Cache-Control头消息。结果像是发生了反倒的事务。

出口的结果依旧依旧是错的,并不曾被缓存
图片 253

无法更改“max-age”头信息是ASP.NET
2.0中的bug。因为“max-age”被设置成零,而“max-age”的值等于零就意味着不供给缓存,所以ASP.NET
2.0才把“Cache-Control”设置为“private”。所以使ASP.NET
2.0重临正确的缓存响应的头音讯是不可行的。

简短节说。反编写翻译HttpCachePolicy类(Context.Response.Cache对象的类)之后,笔者发觉了之类代码:
图片 254

不知怎么,this._maxAge的值会被设置成零,看一下那段代码“if
(!this._isMaxAgeSet || (delta <
this._maxAge))”,它用于幸免_maxAge被设置得过大。由于这一个题材,大家需绕过Set马克斯Age函数,然后利用反射去一向的装置_maxAge的值。

图片 255[WebMethod][ScriptMethod(UseHttpGet=true)]
图片 256public string CachedGet2()
图片 257图片 258图片 259{
图片 260    TimeSpan cacheDuration = TimeSpan.FromMinutes(1);
图片 261
图片 262    FieldInfo maxAge = Context.Response.Cache.GetType().GetField(“_maxAge”, 
图片 263        BindingFlags.Instance|BindingFlags.NonPublic);
图片 264    maxAge.SetValue(Context.Response.Cache, cacheDuration);
图片 265
图片 266    Context.Response.Cache.SetCacheability(HttpCacheability.Public);
图片 267    Context.Response.Cache.SetExpires(DateTime.Now.Add(cacheDuration));
图片 268    Context.Response.Cache.AppendCacheExtension(
图片 269            “must-revalidate, proxy-revalidate”);
图片 270
图片 271    return DateTime.Now.ToString();
图片 272}

它将赶回下列头消息:
图片 273

今昔“max-age”被设置成了60,所以浏览器将把数量缓存60秒。如若60秒内你利用了同一的调用,那么它将重回相同的结果。上边是一个人作品显示从服务端再次来到日期的输出结果:
图片 274

1分钟后,缓存过期并且浏览器再度向服务器发送2个请求。客户端代码如下:

图片 275function testCache()
图片 276图片 277图片 278{
图片 279    TestService.CachedGet(function(result)
图片 280图片 281    图片 282{
图片 283        debug.trace(result);
图片 284    });
图片 285}

此处还有另贰个标题亟需缓解。在web.config文件中,你会看到ASP.NET
AJAX扩展了上面那一个因素:

图片 286<system.web>
图片 287        <trust level=”Medium”/>

它会制止大家设置响应对象的_maxAge,因为它须求反射。所以您无法不删除trust成分也许设置它的level属性为Full

图片 288<system.web> 
图片 289    <trust level=”Full”/>

当“this”不是您觉得的“this”的时候
Atlas回调函数不会在它们被调用的一模一样上下文中执行
。例如,假使你在一个JavaScript类里像那样使用3个web method

图片 290function SampleClass()
图片 291图片 292图片 293{
图片 294    this.id = 1;
图片 295    this.call = function()
图片 296图片 297    图片 298{
图片 299        TestService.DoSomething( “Hi”, function(result)
图片 300图片 301        图片 302{
图片 303            debug.dump( this.id );
图片 304        } );
图片 305    }
图片 306}

当您调用“call”方法的时候会发生哪些?你会在debug中收获“1”吗?不会,你将在debug中拿走“null”,因为那几个“this”不再是类的实例。那是每壹人时常会犯的不当。那在Atlas的文书档案里如故没有有关认证,作者发觉许多开发人士都开支时间去追寻那是怎么错误。

案由是那般的。我们知晓借使JavaScript事件被触发,那么“this”便是辅导致事件发生的分外HTML成分,所以一旦你像上边那样写的话:

图片 307function SampleClass()
图片 308图片 309图片 310{
图片 311    this.id = 1;
图片 312    this.call = function()
图片 313图片 314    图片 315{
图片 316        TestService.DoSomething( “Hi”, function(result)
图片 317图片 318        图片 319{
图片 320            debug.dump( this.id );
图片 321        } );
图片 322    }
图片 323}
图片 324
图片 325<input type=”button” id=”ButtonID” onclick=”o.onclick” />

比方你单击了这么些按钮,就会意识“ButtonID”代替了“1”。原因正是那个按钮正在调用“call”方法。所以,这么些调用在按钮对象的上下文中成功,而“this”就被映射为那个按钮对象。

一律的,当XML
HTTP触发了足以捕获和鼓舞回调函数的onreadystatechanged事件的时候,代码执行还是在XML
HTTP的内外文中。它是触发了那几个事件的XML
HTTP对象。结果,“this”就对准了XML
HTTP对象,而不是您本人的在回调函数被申明处的类。

为了使回调函数在类的实例的光景文中激发,所以要让“this”指向类的实例,你须求做如下改变。

图片 326function SampleClass()
图片 327图片 328图片 329{
图片 330    this.id = 1;
图片 331    this.call = function()
图片 332图片 333    图片 334{
图片 335        TestService.DoSomething( “Hi”, 
图片 336            Function.createDelegate( this, function(result)
图片 337图片 338        图片 339{
图片 340            debug.dump( this.id );
图片 341        } ) );
图片 342    }
图片 343}

此处的Function.createDelegate用来创设一个调用“this”上下文下的特定函数的委托。它能够给函数提供“this”的上下文。Function.createDelegate被定义在Atlas运维时。

图片 344图片 345Function.createDelegate = function(instance, method) 图片 346{
图片 347图片 348    return function() 图片 349{
图片 350        return method.apply(instance, arguments);
图片 351    }
图片 352}

HTTP POST要比HTTP GET慢,不过ASP.NET AJAX私下认可用的是HTTP POST
默许情形下,ASP.NET AJAX的拥有web service调用都应用HTTP POST格局。HTTP
POST方式要比HTTP
GET格局提交越来越多的代价,它通过互连网传输更加多的字节,因而就要占用宝贵的网络传输时间,也使得ASP.NET要在服务端做一些非凡处理。所以,在也许的情状下你应当选拔HTTP
GET方式。但是,HTTP
GET情势分歧意你将对象作为参数字传送输,你不得不传输数字、字符串和日期。当您处理叁个HTTP
GET调用的时候,Atlas会组织1个被编码的U奥迪Q7L并应用它。所以,你不该传输很多内容而使U汉兰达L超越20肆拾三个字符。据本身当下所知,那是任何UTiggoL的最大尺寸。

为了在1个web service方法中运用HTTP
GET方式,你需求用[ScriptMethod(UseHttpGet=true)]属性修饰这一个格局:

图片 353[WebMethod] [ScriptMethod(UseHttpGet=true)] 
图片 354public string HelloWorld()
图片 355图片 356图片 357{
图片 358}

POST与GET的另五个题材是,POST要求四次网络传输。当你利用POST的时候,web服务器会头阵送八个“HTTP
100
Continue”,那意味web服务器已经准备好了收纳内容。之后,浏览器才会发送实际数目。所以,因为POST请求的初阶阶段要比GET格局开支更加多的小时,在AJAX程序里互连网延迟(你的微型计算机和服务器之间的数码传输)是要予以丰富珍重的,因为AJAX适合处理部分小的内需在皮秒级的时日内完结的调用。不然程序会不流畅并且让用户认为厌烦。

Ethereal是二个很好的工具,它能够侦测到POST和GET的图景下到底发生了怎么样:
图片 359

从上边的图中,你能够看出POST方式在准备发送实际多少以前,要从web服务器请求一段“HTTP
100
Continue”的确认音讯,那将来才会传输数据。另一方面,GET方式传输数据是不要求任何确认的。

从而,当您要从服务端下载页的某一有个别、1个表格恐怕是一段文本之类的时候就应有利用HTTP
GET方式。而只要要像web
form这样以提交的格局发送数据到服务端的话就不应有使用HTTP GET形式。

结论
上面所说的这一个高档技术都曾经在Pageflakes中贯彻了,那里本身并从未提及它的详细实现格局,可是原理都关乎了,所以,你能够放心地利用那些技能。这几个技巧将节约你化解难点的时光,大概在支付环境中你一贯没认识到那些标题,然而当您科学普及安排网站之后,来自世界内地的访问者就将直面那个题材。一初步就天经地义的达成这么些技能将会大大节省你的费用和客户援救的时辰。请同时关注本身的博客以赢得越来越多的技能。

相关文章

网站地图xml地图