用ASP.NET 2.0实现AJAX风格的Web开发

全面掌握ASP.NET 2.0教程:从基础到实践 本文还有配套的精品资源,点击获取 简介:ASP.NET 2.0是构建动态网站和Web应用程序的微软框架,本教程旨在向初学者全面介绍其新特性、工具和技术。教程包括ASP.NET 2.0的核心概念、母版页、主题、登录控件、数据控件、PostBackUrl和PostBackOptions、AJAX支持、WebParts以及配置和部署等内容。通过实例和实践任务,教程帮助学习者掌握W... 阅读详情
提要 在过去的几个月中,基于AJAX技术开发高度交互的Web应用程序的设计模式迅速流行开来。现在,具有高度可配置性的Web应用程序,例如Google Maps和A9,都在综合利用这些技术来创造丰富的客户端用户体验。其实,结合AJAX技术进行Web开发并非最近的研究成果,只不过这些技术一直以来不断得到持续更新和改进。

  本文中我有三个目的。首先,我想提供一个AJAX风格应用程序的高级概述。其次,我想详细地描述ASP.NET 2.0的异步回调机制。最后,我想对构建AJAX风格应用程序的工具和框架的未来改进作一下展望。

  归纳来看,AJAX风格的Web应用程序展示了下列特征:

  · 到Web服务器的异步请求-在用户等待来自于Web服务器的响应时,浏览器用户接口不会被堵塞,而是可以继续响应用户的交互。

  · 高度依赖于用JavaScript编写的基于浏览器的逻辑-W3C DOM的最新改进和标准化为实现动态的客户端UI更新提供了支持。

  · 在浏览器和Web服务器之间的基于XML数据的交换-XMLHttp对象使得与Web服务器进行通讯而不需要重载页面成为可能。

  一个AJAX应用程序和传统型Web应用程序之间的最大差别是,每次用户交互不会导致每一个HTTP请求都被发送到Web服务器;而是,用JavaScript实现的基于浏览器的逻辑掌握着控制权,之后再由该控制决定是局部处理请求还是向服务器作异步调用。一旦到服务器的异步调用结束,客户端逻辑立即适当更新UI的相关部分。这种方式具有下列优点:

  · 用户体验更为丰富。例如,当一个Google地图用户沿一个方向拖动地图时,系统就会在后台向服务器发出一个异步请求,结果是他能够在超出屏幕边界后继续拖动。这样以来,当用户进一步拖动地图时,新的图像已经可用了。这导致一种响应更快的感觉。

  · 既然跨越基于XMLHttp的到服务器的调用状态并没有丢失,那么,AJAX应用程序就可以避免每次都重新生成UI界面。

  · 更多的逻辑位于浏览器端,从而减少了到Web服务器的来回请求的数量,进而全面改进系统的潜力。

  尽管存在这么多的优点,然而AJAX风格的应用程序还是存在一些不足之处。例如,AJAX风格应用程序的开发是比较困难的,因为缺乏相应的框架(一组类似于Windows MFC工具包的UI类)和IDE(调试,可视化设计,等等)支持。另外,基于AJAX进行开发要求一个人必须至少掌握两种语言(DHTML和JavaScript)。而且,AJAX风格应用程序的编码需要更长的时间,因为它需要另外的测试以使其支持多浏览器版本和类型。最后,由于基于JavaScript的源码为终端用户可存取,所以开发过程中的安全分析也变得非常重要。

  幸好,例如Atlas,AJAX.NET和Google Maps API等工具的出现为将来构建AJAX风格的应用程序提供了更好的支持。接下来,我们将讨论一下,对于构建AJAX风格应用程序的支持技术的发展历程以及我们能够从最新发布的工具集Atlas得到怎样的期望。

  让我们首先讨论XMLHttp对象。这个对象最初为微软所引入,以后在其它平台(包括Mozilla和苹果公司的Safari浏览器)上也得到实现。XMLHttp支持到Web服务器的异步请求,这样可以允许客户端基于JavaScript逻辑调用Web服务器而不需要重载整个页面。

  换句话说,在后台与Web服务器的交互而不引起整个页面重载是完全有可能的。

  至于XMLHttp对象的使用则相当直接。为简单起见,让我们仅考虑IE特定的语法。其实,XMLHttp在其它浏览器上的实现语法与这里的讨论也很类似。

request = new ActiveXObject("Microsoft.XMLHTTP");
if (request){ request.onreadystatechange = CallbackHandler;
 request.open("GET", URL, true);
 request.send();
}
function CallbackHandler(){
 if ((request.readyState == 4) && (request.status == 200){
  string response = request.responseXML;
  //更新UI的相关部分
 }
}

  在上面的代码片断中,第一步实现实例化Microsoft.XMLHttp类。第二步设置我们刚刚创建的XMLHttp实例的属性,其中包括当XMLHttp请求完成时将得到控制的回调函数的地址。因为我们在向服务器作异步调用(通过把open方法的第三个参数设置为true来实现),所以我们需要回调函数的地址。在回调函数实现过程中,我们作额外的检查以确保完成请求。

  你从上面的示例代码中可以看出,以独立方式使用XMLHttp对象是相当简单的。然而,把XMLHttp集成到HttpPage生命周期的其它部分中是比较困难的-例如,如何确保服务器端的方法调用能够存取页面中其它控件的状态呢?为了正确初始化这些控件的状态,服务器端的回调处理需要经历一个与回调过程类似的HttpPage生命周期。直接使用XMLHttp对象的其它挑战是,作为开发者,我们需要考虑不同的浏览器类型。幸好,ASP.NET 2.0提供了一个可重用的模式-它能够使得存取回调功能非常容易。注意,随同ASP.NET 2.0一同发行了若干控件,包括GridView,TreeView等,都综合利用了回调机制。

  让我们先看一下服务器端实现原理。首先,在服务器端要定义一个新的接口IcallBackEventHandler。任何ASPX页面(或打算支持客户端回调的控件)都需要实现这个ICallBackEventHandler接口。ICallBackEventHandler接口定义了一个称为RaiseCallbackEvent的方法。这个方法使用一个字符串类型的参数并且返回一个字符串。

  在客户端,为了初始化回调功能,需要调用一个特殊的JavaScript函数。你可以通过调用ClientScriptManager.GetCallbackEventReference来获得一个到这个特殊的JavaScript函数的引用。到GetCallbackEventReference的调用将产生一个回调引用。当调用此回调函数时,你只需要传递一个字符串类型的参数。这是与服务器端的RaiseCallbackEvent签名一致的。这就是你在客户端建立回调机制所需做的一切。其它的把客户端回调函数钩(hook up)到服务器端的IcallBackEventHandler接口的RaiseCallbackEvent方法的实现则是由框架来完成的。前面提到的初始化回调机制的特殊JavaScript函数使用了另外两个参数(__CALLBACKPARAM和__CALLBACKID)作为回馈数据,它们分别代表传递到调用者的字符串参数和控件的ID。在服务器端,ASP.NET检测其它两个参数的存在并且会把请求路由到适当的控件,这将导致调用目标控件上的RaiseCallbackEvent方法。为了解决前面提到的页面上的控件的初始化问题,ASP.NET运行时刻在服务一次回调时提供了一个简化版本的HttpPage生命周期。这一周期包括浏览页面初始化的某个具体阶段,观察状态加载,页面加载和回调函数事件处理等。一旦回调函数事件被控件所处理,HttpPage生命周期的其它阶段就会被跳过。

  为了帮助更好地理解ASP.NET 2.0的回调机制,发行包中包括了一个简单的进度条控件,它依靠回调来决定服务器确定的一项任务的状态。下面的列表1显示了该ProgressBar控件的代码。为了支持客户端回调函数,这个控件实现了ICallbackEventHandler接口。为了演示之目的,RaiseCallbackEvent方法实现简单地查找存储在会话中的一个计数器,每次给计数器加1,并且把新值返回到客户端。最后,列表2显示了负责初始化该回调函数的JavaScript代码。它使用了this.Page.ClientScript.GetCallbackEventReference来获得一个到需要初始化回调的函数的安全引用。

  列表1:ProgressBar.cs

public class ProgressBar : System.Web.UI.Control, System.Web.UI.ICallbackEventHandler{
private int PercentCompleted{
 get
 {
  if System.Web.HttpContext.Current.Session["PercentComplete"] == null) {
   System.Web.HttpContext.Current.Session["PercentComplete"] = 1;
 } 
 else {
  System.Web.HttpContext.Current.Session["PercentComplete"] =(int)System.Web.HttpContext.Current.Session["PercentComplete"] + 1;
 }
 return (int)System.Web.HttpContext.Current.Session["PercentComplete"];
}
set
{
 System.Web.HttpContext.Current.Session["PercentComplete"] = 1;
}
}
public string RaiseCallbackEvent(string eventArguments) {
 int percent = this.PercentCompleted;
 if (percent > 100)
 {
  this.PercentCompleted = 1;
  return "completed";
 }
 else
 {
  return percent.ToString() + "%";
 }
}
protected override void OnPreRender(EventArgs e) {
 this.Page.ClientScript.RegisterClientScriptBlock(typeof(ProgressBar),
"ProgressBar", this.GetClientSideScript(), true);
 base.OnPreRender(e);
}
protected override void Render(HtmlTextWriter writer) {
 System.Text.StringBuilder sb = new StringBuilder();
 sb.Append(@"<table id=""ProgressBarContainer"" bgcolor=""LightSteelBlue""
 border=""0"" width=""400"" style=""DISPLAY:none; POSITION: absolute;
 Z-INDEX: 10"">");
 sb.Append(@"<tr><td colspan=""3"" style=""padding:3px 2px 2px 10px"">");
 sb.Append(@"<font face=""Verdana, Arial, Helvetica, sans-serif"" size=""2"">");
 sb.Append(@"<span id=""ProgressBarLabel"">Uploading...</span>");
 sb.Append(@"</font></td></tr><tr><td>");
 sb.Append(@"<font size=""1""> </font></td><td bgcolor=""#999999""
 width=""100%"">");
 sb.Append(@"<table id=""ProgressBar"" border=""0"" width=""0""
 cellspacing=""0"">");
 sb.Append(@"<tr><td style=""background-image:url(progressbar.gif)"">
 <font size=""1""> </font></td>");
 sb.Append(@"</tr></table></td>");
 sb.Append(@"<td><font size=""1""> </font></td></tr>");
 sb.Append(@"<tr height=""5px""><td colspan=""3""></td></tr>");
 sb.Append(@"</table>");
 writer.Write(sb.ToString());
 base.Render(writer);
}
private string GetClientSideScript() {
 System.Reflection.Assembly dll =
 System.Reflection.Assembly.GetExecutingAssembly();
 StreamReader reader;
 reader = new StreamReader(dll.GetManifestResourceStream("ProgressBar.txt"));
 StringBuilder js = new StringBuilder(reader.ReadToEnd());
 string fp = this.Page.ClientScript.GetCallbackEventReference(this, "", "UpdateProgressBar", "");
 js.Replace("##InitiateCallBack##", fp);
 reader.Close();
 return js.ToString();
}
}

  列表2:ProgressBar.js

<script language="javascript">
var isCompleted=false;
//这个函数初始化到服务器端的回调
function DrawProgressBar(){
 ##InitiateCallBack##;
 if (!isCompleted) {
  window.setTimeout('DrawProgressBar()',200);
 }
 else
 {
  isCompleted=false;
  document.getElementById("ProgressBarContainer").style.display = 'none';
 }
}
//当thecallback完成时,下列函数被调用
function UpdateProgressBar(percent){
 if (percent == 'completed'){
  isCompleted=true;
 }
 else{
  document.getElementById("ProgressBar").width = percent;
 }
}

 

  通过使用在ASP.NET 2.0提供的客户端回调函数,实现进度条控件是比较直接的,因为在控件和客户端之间传递的数据仅是一个简单的字符串。然而,一旦我们把其它数据类型也添加到其中,我们就遇到在JavaScript和.NET类型系统之间不匹配的问题。遗憾的是,ASP.NET 2.0中的回调函数实现对此并无多大帮助。任何想使用多种数据类型(简单类型和复杂类型)的应用程序,都要实现一种自己的定制模式。

  幸好,这种限制能够通过使用一个AJAX.NET开源库来加以克服,AJAX.NET实现了一种基于代理的方式来调用服务器端函数。AJAX.NET定义了一种称为AJAXMethod的定制属性。当一个服务器端方法用AJAXMethod加以修饰时,一个基于JavaScript的客户端代理将被HttpHandler(它是AJAX.NET库的一部分)自动生成。不同于ASP.NET 2.0,它支持单个参数的字符串类型以便用于回调实现。AJAX.NET支持整数,字符串,双精度数,DateTime,DataSet等多种类型。

  Bertrand Le Roy建议使用AJAX.NET来处理JavaScript和.NET类型系统之间的差别。他创建了一种称为EcmaScriptObject的服务器端控件-它基于.NET技术重新创建了JavaScript类型系统。其想法是,用.NET重新生成一种客户端对象图。当转换发生在服务器端时,这种方法显得更有意义。

  即使我们有了一种类型安全的方法来调用回调函数,但是,我们还面临其它的挑战。JavaScript担当起了把AJAX应用程序的各个部分组合到一起的"胶水"的作用。当然,相应地,对JavaScript的依赖性也进一步增加。遗憾的是,尽管JavaScript是一种强有力且通用的语言,但是它并没有实现面向对象的原则。这意味着,要实现代码重用可能更为困难。当然,可以使用一些技巧来使JavaScript看上去更象传统的面向对象语言。不过即使如此,要实现托管语言中的例如事件和代理等特征仍然相当困难。

  其它困难还包括:缺乏一个可重用框架来进一步提高JavaScript的开发效率。如果有一种基于JavaScript的能够隐蔽不同执行环境区别的UI框架或许更好些。另外,如果能够创建一组类,它们可以用一种安全的方式(相对于手工编码SOAP包并使用XMLHttp来传递它们)来调用Web服务,也会相当不错。

  最近来自微软的Atlas工程许诺要重点解决这类问题。这是一种极大程度地简化AJAX风格开发的伟大尝试。Atlas提供了一种新的JavaScript框架(注意,下面是基于微软的一次初步宣布,以后有可能发生改变)-UI开发工具包。这其中包括:支持诸如拖放和数据绑定等特征的常用控件;调用Web服务的SOAP栈;隐蔽浏览器差别的浏览器兼容层;包括例如本地缓冲等内容的客户端构建模块。另外,ASP.NET团队还计划为ASP.NET开发其它构建模块,例如配置管理,成员管理等,以便把它们用作Web服务端点,从而实现可以直接从JavaScript中对Web服务进行存取-例如可以容易地从客户端存取个人信息。最后,Atlas工程还计划扩展JavaScript语法以便包括接口、生命周期管理和multicast事件。

  据说,接下来的几个月将是令AJAX开发者激动的日子。因此,我非常希望本文能够激起您对AJAX的兴趣,并在你以后构建下一代Web应用程序时优先考虑使用这一技术

ASP.NET2.0 AJAX ASP.NET2.0 AJAX包括:ASP.NET 2.0 AJAX Extensions和ASP.NET Futures CTP.放心下载可用!<br>支持vs2005sp1!不要用vs2005的哟!否则web.config中会出现错误的! 立即下载

相关推荐

ASP.NET 2.0 AJAX Extensio(微软官网下载)

ASP.NET 2.0 AJAX Extensio(由微软官网提供)

安装ASP.NET AJAX (一安装)

2.3 安装ASP.NET AJAX 前面讲了这么多也许令人昏昏欲睡的概念,相信你已经迫不及待地想尝试一下ASP.NET AJAX了,那么就让我们从安装开始吧! 2.3.1 预先需求 若要安装并使用ASP.NET AJAX框架的全部功能进行开发,那么你的操作系统必须是Windows 2000、Windows XP、Windows Server 2003或Windows Vista,并应该安装...

宁波阿成的博客 571

Microsoft Ajax For asp.net2.0

Microsoft Ajax For Asp.net2.0及demo

AjaxPanel自定义控件实现页面无刷新数据交互(做了个示例程序, 效果确实比较Cool, 用法非常简单! )(示例代码下载)

(一) . 简要          AjaxPanel, 一个自定义控件, 只要在页面中将AjaxPanel作为父控件, 则它内部的控件在运行时无刷新.           做了个程序试了一下果然比较Cool !  下面介绍一下具体配置, 配置也比较简单.(二). 运行示例图(三). 配置     1. 把 AjaxPanel 添加到工具箱中. 步骤如下:  2

★(ChengKing)【夜战鹰】【产品级性能调优与故障诊断分析】★ 5756

asp.net 2.0+ajax 的简单示例

asp.net 2.0+ajax 的简单示例哦,大家可以学习看看。

面积二次矩second moment of area 极惯性矩polar moment of area 转动惯量moment of inertia面积一次矩first moment of area

看论文记录一下力学的名词专业术语,后面可以查看。

subtitle_的博客 5370

Hermes Agent 进化机制:状态迁移而非版本更新

Agent 运行时环境(ARE)是一种支撑智能体持续演化的底层架构,其核心在于对 Memory、Tool、Context 三大状态域的协同管理与原子性迁移。区别于传统软件升级,Hermes 的更新本质是可观察、可干预、可回滚的状态演化过程,依托快照(snapshot)、归档(archive)和合规备份(backup)三层机制实现时间维度上的自我修复能力。该机制保障了状态一致性、行为可预测性与故障隔离性,广泛应用于金融客服、政务审批、跨境电商等高可靠性场景。理解 Hermes 的 snapshot captu

weixin_34375251的博客 404

附录B:Standard Delay Format(SDF)(上)

本附录将介绍标准延迟标注格式,并说明了如何在仿真中执行反标。 延迟格式描述了设计网表的单元延迟和互连走线延迟,无论设计是用两种主要硬件描述语言(VHDL或Verilog HDL)中的哪一种所描述的。 本章还会介绍仿真的反标(backannotation),STA的反标其实是一个简单直接的过程,其中DUA中的时序弧将由SDF所指定的延迟进行标注。

To the beyond and infinity! 5413

图集工具生成图集的原理_图集:Microsoft的Ajax工具包

图集工具生成图集的原理 微软正在组装一个用于完成Ajax事情的工具包,称为Atlas。 微软公司的斯科特·古思里 ( Scott Guthrie)表示 ,这看起来像是ASP.NET 2.0。 令人放心的是,他说“ Atlas客户端脚本框架将在所有现代浏览器上以及任何Web服务器上都可以使用”,这意味着它们正在以跨浏览器的方式实现Ajax风格的远程脚本,这确实是一个不错的举措; 过去,MS在这种情况...

171

深度学习的unfold操作

对于彩色图像这样的三维数据,unfold操作会对每个通道分别进行上述的二维展开操作。例如,一个 RGB 图像,在对其进行unfold操作时,红色通道、绿色通道和蓝色通道的数据都会被独立地按照定义的窗口和步长展开,然后将这些展开后的通道数据按照原来的通道顺序组合在一起,形成新的张量。与我们熟悉的卷积类似,unfold也是使用一个特定大小的窗口和步长自左至右、自上至下滑动,不同的是,卷是滑动后与核求乘积(所以取名为卷积),而unfold滑动后不求乘积,是将窗口内的数据展开。

xulibo5828的博客 2168

国内网络环境下Leaflet加载OpenStreetMap地图的5种替代方案(附可用瓦片地址)

本文针对国内网络环境下Leaflet加载OpenStreetMap地图的常见问题,提供了5种可用的瓦片替代方案,包括OpenStreetMap.fr HOT、OpenStreetMap.de、CartoDB、Stamen和Thunderforest,并附上详细的代码示例和选择建议,帮助开发者解决地图加载问题。

qsc901234的博客 1699

ASP.NET 2.0实现AJAX的Web开发

<!--google_ad_client = "pub-2947489232296736";/* 728x15, 创建于 08-4-23MSDN */google_ad_slot = "3624277373";google_ad_width = 728;google_ad_height = 15;//--><script type="text/javascript"

zgqtxwd的专栏 425

[软考]系统架构设计师 备考经验分享(一) - 备考计划篇

前言 上周末刚刚结束了软考架构师的考试,自我感觉考的还可以,大概率是过了。 两次参加软考,一次中级嵌入式,一次高级架构师,都是备考不到两个月时间,尤其是架构师这次考试内容和本职工作有不小的差别,并且需要同时备考三个科目,在高强度地备考中感觉是摸索出到了一点软考的技巧与经验。 打算趁还记得,赶紧写几篇文章做下梳理总结,算是给将来自己考系分、高项或者其他考试做个记录,也希望能够帮到正在备考的大家。 先把第一步,个人的备考计划分享给大家。 自身情况分析 首先,请大家一定先明确三个问题,这三个问题会直接影响到你的

_ 6405
上一篇: ASP.NET中实现模版的动态加载
下一篇: C#中屏蔽窗体关闭的消息
mzphp
博客等级 码龄21年 9粉丝 18原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值