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

[翻译]ASP.NET AJAX之里揭秘

原文发布日期:2006.12.22
作者:About Omar Al
Zabir
翻译:webabcd
审校:Tony Qu 

介绍
微软新近宣布了ASP.NET AJAX的Beta
2版。虽然它们是一个可怜有力的框架,但是当你在web
2.0的社会风气被如出一个当真的AJAX
web站点的话,就会见遇上多问题,而且若几找不至其它相关文档。本文中,我用介绍一些当开发Pageflakes面临所读到的高等经验。我们用会见看到ASP.NET
AJAX一些效应的得失,如批调用(Batch
Call),调用超时,浏览器调用拥堵问题,ASP.NET 2.0受web
service响应缓存的bug等等。

本文最后更新:2006年12月22日,针对ASP.NET AJAX
RC更新(译注:适用于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类包括了28单扩大(译注:现在时有发生34只),你得管其拖拽到页面及,然后经设置有特性就得产生十分充分的职能。看看那些例子你不怕会见明白ASP.NET
AJAX给咱们带了多么强大的功效。

于我们早期开发Pageflakes的上,Atlas还处于幼儿等。我们只能使用page
method和Web
Service方法来调用Atlas的表征。我们只好开我们和好的拖拽、组件构造、弹出、伸缩/展开等特点。但是本,Atlas提供了所有这些职能,所以可以大大节约我们的出时间。最令人好奇之是Atlas提供了web
service代理的表征。你可以指定<script>标签及一个.asmx文书,然后你会获得一个JavaScript类,它见面冲web
service的概念为科学的转。这使得添加或移除一个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版本(之前的版)里发一个特性,就是允许在一个呼吁里含有多只请求。它工作经常您切莫见面专注到其他事情,而且也不需要写任何异样的代码。一旦您利用了批调用特色,那么以平软批调用中,其中具有的web
service调用都见面被实施,所以她将缩减回发时间与总响应时间。

实在的响应时间或许回落了,但是咱发到的缓却变长了。如果来3只web
service被批量调用,那么首先独调用不会见首先完成,而是所有3单调用会在同之时就。如果你的各国一个web
service调用得后都更新UI的话,将不见面雷同步一步更新,而是于有着调用一起好后再次一并更新UI。结果,你免会见视UI被高速更新,而是于UI被更新之前起一个添加时之延。如果说调用中的外一个(比如第3个调用)下载了汪洋数据,那么以享有的3只调用完成前用户不见面视另外变动。所以首先个调用的推行时几乎接近3单调用的终究执行时。虽然减少了实际的总共拍卖时,但是会感觉到有再丰富之推移。当每个调用都只导少量数的上批调用是很好的,这样,3个袖珍调用就会见以一如既往赖回发中实施完毕。

受咱省3独调用是什么样一个一个深受得的,这将证明这些调用实际上是怎么被实施之。
图片 1

老二只调用到达服务端的时间如果较第一个调整用长,因为第一单调用吃特了带富。同样的缘故,下载呢即会见花费还多的光阴。浏览器同时打开了少于单连续到劳动器端的接连,所以于同一时间,只能处理两只调用。一旦第一独调用或第二个调用完成后,第三单调用才能够为拍卖。

当3独web service在平不良呼吁中受批调用的当儿:
图片 2

此地共下载时间将会晤有削减(如果IIS的减少功能启用的言语),并且独自待一软网络响应。所有的3个调用一浅让发朝届服务端后整个履,组合而成的老三只调用的应是于平赖调用中下载。但是对用户来讲,他们会感觉速度变慢了,因为UI的更新发生在拥有批调用就之后。这个批调用好的终究时间连要善用两个调用的。并且,如果你闹大量之一个又一个底UI更新,IE将会见结冰一段时间,这将让用户带来一个坏之体会。一些上,时间较丰富的UI更新会促成浏览器出现“白屏”,但是FireFox和Opera不会见发生夫题材。

批调用也是发一些长的。如果您的IIS启用了gzip压缩功能的话,将本着合结实开展削减而不是分别回落每个结果,那么到底下载时长就见面少单独调用的下载时长。所以,通常批调用都是一些袖珍调用的语会比好。但是只要调用会发送或返回较生数额来说,比如20KB,那么最好好就算变以批调用了。批调用还有其他一个题目,比如说前片只调用非常小,第3独调用十分深,如果立刻3个调用被批调用的话,那么前少单稍的调用就要延期很丰富时,因为第3独雅十分。

不好之调用会使好之调用超时
比方出些许独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做同样糟糕“灵魂外科手术”,这个方法会要求每个调用在过晚都再度试一次于。为了促成它,我们要截获所有web
method调用并且在onFailure回调函数中犯个钩,如果失败的由来是过,onFailure将再调用相同的web
method

另外一个亟需关爱之意识是当我们外出旅行感到疲惫时,想经过酒店或者机场的无线网络连接到互联网访问Pageflakes的时,首不善访问总是不成功,并且有着的web
service调用在第一蹩脚尝试着老是败。直到我们刷新之前还不见面做事。这为是咱若贯彻web
service调用这自动重试的其余一个第一由,它正可以化解之题目。

这边我会告诉您怎么开。Sys$Net$WebServiceProxy$invoke函数是负担处理所有web
service调用的。所以,我们要通过一个自定义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}

运作的上,它以把每个超时调用都还试一涂鸦
图片 121

此处您得望第一个点子成功了,所有其他超时的调用都见面被重试。而且若呢会看重试一软后的调用都事业有成了。发生这种状态是以以重试中劳动端的不二法门不见面召开过处理。所以,这说明了咱们的贯彻方式是天经地义的。

浏览器就允许同一时间内生少只调用,此时非会见履另外任何命令
浏览器在同一时间内只能针对一个域名处理两个冒出的AJAX调用。如果你出5单AJAX调用,那么浏览器首先将会见处理两独,然后等里一个就后,再处理外一个调用,直到剩余的4单调用都让得。此外,你不用指望调用的实践顺序会及您处理调用的逐条相同,这是干吗吗?
图片 122

刚好而你所显现,调用3要下载比较好的数额,所以它所待的流年就会比调用5要增长,事实上,调用5会见以调用3事先实施了。

用,在HTTP的社会风气里,这些都是不行预知的。

当排里生差不多被少数单调用的时候浏览器将非会见应
品尝这样做,在首破看时打开任何一个加载了大气RSS的页(如Pageflakes,
Netvibes,
Protopage),在加载中,你可以品味着单击一个链接到其他一个站点或试着直接看另一个站点,那么您就见面发觉浏览器不见面有其他响应。直到浏览器里富有班的AJAX调用都好后,浏览器才会领其他一个动。这是IE的一个比较不好之地方,但是Firefox和Opera就无见面产生之题材。

其一题材是,当您出大气之AJAX调用的时光,浏览器会将所有的调用放到一个行列里,在同一时间内只执行中的少单。所以,如果你单击了有链接或者转发另一个站点,那么浏览器必须等在得到任何一个调用之前在执行的调用完成后才见面失掉处理。解决是题材之点子尽管是防浏览器在同一时间内发差不多受简单个底调用在列里。我们需要保持一个自己之行,然后打咱的排里拿一个一个调用的发到浏览器的班中。

是解决方案是挺棒,它可以预防调用内的撞:

图片 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            // 得到第一单调用队列
图片 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封装了一个web
method调用,它具有真正web服务调用的有所参数,并且更写了onSuccess和onFailure回调函数。我们想明白当一个调用完成或者失败了的时段,如何从咱的排里调出任何一个调用。GlobalCallQueue保存了web服务调用的列表。无论何时,当一个web
method被调用时,我们先行使对准GlobalCallQueue中的调用进行排队,并打咱团结一心之序列里一个一个之实践调用。这样即使足以确保浏览器在同之时日里不见面有多被片独之调用,所以浏览器就未见面停响应。

以保证队列是基于调用的,我们得像前那么再重写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的说话也是可以缓存的。这个缓存是依据URL的。如果是均等URL,且保险存在和一个处理器里,那么数量以起缓存里加载,而休会见于服务器再请求。基本上,浏览器可缓存任何HTTP
GET请求又返回基于URL的让缓存数据。如果你拿一个XML HTTP调用作为HTTP
Get方式吧,那么服务端将回到一些特之腔信息,用于通知浏览器对相应做缓存,之后再行调用相同之始末,结果虽会就从缓存中被归,从而减少了网络传输延迟和下载时间。

在Pageflakes中,我们对用户的状态做了缓存,所以当用户还访问的下会起浏览器的缓存里立马收获缓存数据,而休用经过服务端。因此次破加载时间会见变换得好抢。我们吧缓存了用户的一些行为所出的结果。当用户还召开相同行为经常,缓存结果虽会及时从用户之本地缓存中加载,从而减少了网络传输时间。用户会体会到一个飞加载与赛响应的站点,获得速度会发出举世瞩目增强。

以此艺术就是拍卖Atlas web service调用时假如采用HTTP
GET方式,并且要回一些尽人皆知的HTTP头信息告诉浏览器具体而缓存多长时间。如果以应期间你回了一个“Expires”头信息,那么浏览器就会见缓存是XML
HTTP结果。这里而需要返回两只头信息去通知浏览器缓存结果。

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

拖欠消息以通报浏览器要缓存结果直到2030年1月1日。在您处理具有同等参数的以及一个XML
HTTP调用的时候,就拿从电脑的复苏存着加载数据,而无见面经服务端。这里还有再多之操纵缓存的高等级道。例如,有一个条信息通报浏览器缓存60秒,那么浏览器要在60秒以后才会接触到服务端并收获新的结果。当60秒后浏览器本地缓存过期的时段,它吗会见防止从代理服务器端取已缓存的应。

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

被咱来尝试着当一个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被安装得过非常。由于这题材,我们要绕了SetMaxAge函数,然后下反射去一直的装_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分钟后,缓存过期并且浏览器还于服务器发送一个伸手。客户端代码如下:

图片 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类里像这么使一个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会组织一个吃编码的URL并行使它们。所以,你不应该传很多内容要使URL超过2048独字符。据本人时所掌握,这是任何URL的极致充分长。

以当一个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方式传输数据是免需要任何确认的。

因而,当你要由劳动端下载页的有一样片段、一个表格或者是一致段子文本之类的时节即便应该使用HTTP
GET方式。而设要是像web
form那样以授的方式发送数据到劳动端的说话就是未应该用HTTP GET方式。

结论
方所说之这些高档技术都已经当Pageflakes受贯彻了,这里我并不曾提及它的详细实现方式,但是原理都涉嫌了,所以,你可放心地运这些技术。这些技术将节省而解决问题的辰,也许在开条件遭到公根本不曾认识及这些题材,但是当你大部署网站后,来自世界各地的访问者就以给这些问题。一开始即不易的兑现这些技术将会大大节省而的开以及客户支持之光阴。请而关心自己之博客因博取重新多的技艺。

相关文章

网站地图xml地图