AJAX服务器扩展建立在ASP.NET2.0基础之上,包括一组新的服务器控件和服务,用来模拟客户端Ajax行为。这个扩展并不遵循传统意义上的Ajax模型,但响应方式却会给最终用户提供这种假象。
1. ScriptManager
首先上场的是ScriptManger控件,它是Ajax页的在大脑,也是框架中最重要的控件。这个控件在应用AJAX的页面上都要存在。所以,一般来说,把这个控件配置在母板页上是个不错的选择。
1.1 理解ScriptManager
ScriptManger在页面中声明,那么,就可以使用以下代码获得ScriptManager对象的引用
ScriptManager的主要职责是向浏览器发布脚本,它部署的脚 本可以来自ASP.NET AJAX库、服务器上的本地文件、或其它程序集中的内嵌资源 。
如果向页面中增加了这个控件,就会在页面上添加Ajax功能所需要的脚本。自动添加的脚本如下所示:
在一般的ASP.NET 2.0中,一个程序集中的内嵌资源需要通过WebResource.axd,并且经过HTTP处理程序访问。关于WebResource,请看以下网页:
http://www.codeproject.com/KB/aspnet/MyWebResourceProj.aspx
http://blog.joycode.com/ghj/archive/2008/01/14/113719.joy
而在ASP.NET AJAX中,它被一个名为ScriptResource.axd的新 HTTP处理程序取代,它提供了一些额外功能,可以实现本地化的浏览器压缩 。
链接的URL带了两个参数,分别是d和t,d参数表示的经过编码的资源键,t参数表示的是时间戳,指是这个程序集最后一次修改时间。再次加载这个页面,浏览器会识别这个参数,于是用户要获取 资源时不必再次下载,而是使用浏览器缓存的内容。
1.2 部署Javascript文件
ScriptManager控件有一个属性Scripts,其中包含的是ScriptReference对象的集合。可以在页面上包含额外的脚本文件。如下所示:
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Scripts>
<asp:ScriptReference Path="~/scripts/Script1.js" />
<asp:ScriptReference Path="~/scripts/Script2.js" />
<asp:ScriptReference Assembly="Demo" Name="Demo.SuperScript.js" />
</Scripts>
</asp:ScriptManager>
1.3 注册服务
处于Javascript文件是AJAX编程的一个重要方面,不过,由Javascript访问WEB服务来得到数据才是提供AJAX支持的关键。要利用AJAX框架得到WEB服务,必须为要建立本地WEB服务注册一个服务引用
ScriptManager有一个Services属性,其中包含一个ServiceReference对象集合,ServiceReference对象就是一种注册服务的机制,从而可以从Javascript访问这些对象。在http://www.cnblogs.com/shipfi/archive/2009/10/25/1589561.html的2.4节中的例子就是一个典型的Javascript调用WebService的例子。
以下代码展示了如何使用ScriptManager注册本地服务
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Services>
<asp:ServiceReference Path="~/Services/MainService.asmx" />
<asp:ServiceReference Path="~/Services/TestService.asmx" />
</Services>
</asp:ScriptManager>
2. ScriptManagerProxy
一个页面上有且只能有一个ScriptManager控件,如果有多个ScriptManager控件,则会导致页面产生一个InvalidOperationException异常。不过在某些情况下,内容页需要一个服务或者脚本引用可能并非由父页面或母版页中的ScriptManager建立,这些引用 可能只是某一个页面需要,而其它的页面不需要。在这种情况下,ScriptManagerProxy控件就派上用场了。
在某个页面上使用ScriptManagerProcy保证脚本只包含在本页面上。
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
<asp:ScriptManagerProxy ID="ScriptManagerProxy1" runat="server">
<Scripts>
<asp:ScriptReference Path="~/scripts/DummyScript.js" />
</Scripts>
<Services>
<asp:ServiceReference Path="~/Services/MainService.asmx" />
</Services>
</asp:ScriptManagerProxy>
与父控件一样,ScriptManagerProxy也有一个脚本和服务引用集合,可以把ScriptManagerProxy认为是ScriptManager控件的扩展。它的用途是增加ScriptManager所没有包含的引用,使用母版页时这种情况很常见。
3.UpdatePanel控件
UpdatePanel控件是一个Ajax的服务器控件,它与ScriptManager紧密合作,以对页面应用部分页面更新。
UpdatePanel类的ContentTemplate属性定义了页面上动态更新的区域,如果使用UpdatePanel,不会导致一个常规的整个页面回送并刷新整个页面。而会产生一个新型回送,即异步回送(asynchronous postback). 异步回送也会经过页面的生命周期,其处理类似于常规回头,但不会导致页面刷新,这意味着UI和应用逻辑可以保持不变。
可以检测测是否正在异步回送的代码:
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
protected void Page_Load(object sender, EventArgs e)
{
ScriptManager scriptManager = ScriptManager.GetCurrent(this.Page); // 返回ScriptManager实例
if (scriptManager.IsInAsyncPostBack) { // 检查异步回送
// We are doing something cool!
}
}
4.UpdateProgress控件
在异步回送时,如果处理时间比较长,可以通过这个控件来告诉用户正在数据传输的过程中,可以显示一个loading.画面。其有一个AssociatedUpdatePanelID属性,可以将它设置为相关的UpdatePannel,这样,只有当相关的UpdatePanel异步回送时,UpdateProgress控件中的内容才会显示出来。
5.Timer控件
这个控件在客户端创建一个计时器,它会以指定的间隔(单位毫秒)调用回送。一般来说,使用Timer控件,放置在UpdatePannel外面,然后在UpdatePannel控件中UPdateMode属性为Conditional,并且给UpdatePanel增加一个Tiggers属性,ControlId为Timer的ID,EventName为Tick。
6.错误处理
一般的,常规回送期间出现错误,会在屏幕上显示出栈轨迹和错误信息。在这里,异步回送的时候,浏览器会把异常显示在一个对话框中。
对于普通用户,显示异常时的错误信息不是很好的做法。所以ScriptManager控件有一个AsyncPostBackError的事件,就提供一种方法,向用户显示对话框之间可以利用这个变更对话框中的文本。如下所示:
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
protected void Genres_SelectedIndexChanged(object sender, EventArgs e)
{
UpdateGenre();
throw new Exception("Look out!"); // 异步回送时,手动的抛出一个异常
}
protected void Page_Load(object sender, EventArgs e)
{
ScriptManager scriptManager = ScriptManager.GetCurrent(this.Page);
// 指定AsyncPostBackError事件发生后,调用OnAsyncPostBackError处理
scriptManager.AsyncPostBackError += new EventHandler<AsyncPostBackErrorEventArgs>(OnAsyncPostBackError);
}
void OnAsyncPostBackError(object sender, AsyncPostBackErrorEventArgs e)
{
// 变更对话框的显示文字,由"Look out!" –> "We're sorry, an unexpected error has occurred"
ScriptManager.GetCurrent(this.Page).AsyncPostBackErrorMessage ="We're sorry, an unexpected error has occurred.";
}
当然,这个方法也不够完美,因为毕竟弹出对话框对用户来说也不够友好,所以可以使用发生异常回送错误时转到指定的错误页面。这种错误机制可以在web.config的customErrors部分配置:
< customErrors mode ="On|Off|RemoteOnly" defaultRedirect ="ErrorPage.aspx" > </ customErrors >
</ system.web >
以上,mode属性设置为on,则重定向到ErrorPage.aspx页面中,如果设为off,则总是显示栈轨迹。如果设为RemoteOnly,则一个远程机器上的访问才会将用户重定向到错误页面。
ScriptManager控件也提供了一个属性可以覆写这个机制,默认的AllowCustomerErrorRedirect属性设置为true.这个属性会覆写customErrors中的值,如果AllowCustomerErrorRedirect设置为false,则会出现异常时显示对话框:
{
ScriptManager scriptManager = ScriptManager.GetCurrent( this .Page);
scriptManager.AllowCustomErrorsRedirect = false ;
}
AllowCustomErrorsRedirect必须要在Page_load时(或之前)设置,如果在load之后设置,则对customErros中的设置没有影响 。