AJAX全称为“Asynchronous JavaScript and XML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术。 国内通常的读音为“阿贾克斯”和阿贾克斯足球队读音一样。
主要包含了以下几种技术
Ajax(Asynchronous JavaScript + XML)的定义
基于web标准(standards-based presentation)XHTML+CSS的表示;
使用 DOM(Document Object Model)进行动态显示及交互;
使用 XML 和 XSLT 进行数据交换及相关操作;
使用 XMLHttpRequest 进行异步数据查询、检索;
使用 JavaScript 将所有的东西绑定在一起。英文参见Ajax的提出者Jesse James Garrett的原文,原文题目(Ajax: A New Approach to Web Applications)。
类似于DHTML或LAMP,AJAX不是指一种单一的技术,而是有机地利用了一系列相关的技术。事实上,一些基于AJAX的“派生/合成”式(derivative/composite)的技术正在出现,如“AFLAX”。
AJAX的应用使用支持以上技术的web浏览器作为运行平台。这些浏览器目前包括:Mozilla、Firefox、Internet Explorer、Opera、Konqueror及Safari。但是Opera不支持XSL格式对象,也不支持XSLT。
主要包含了以下几种技术
Ajax(Asynchronous JavaScript + XML)的定义
基于web标准(standards-based presentation)XHTML+CSS的表示;
使用 DOM(Document Object Model)进行动态显示及交互;
使用 XML 和 XSLT 进行数据交换及相关操作;
使用 XMLHttpRequest 进行异步数据查询、检索;
使用 JavaScript 将所有的东西绑定在一起。英文参见Ajax的提出者Jesse James Garrett的原文,原文题目(Ajax: A New Approach to Web Applications)。
类似于DHTML或LAMP,AJAX不是指一种单一的技术,而是有机地利用了一系列相关的技术。事实上,一些基于AJAX的“派生/合成”式(derivative/composite)的技术正在出现,如“AFLAX”。
AJAX的应用使用支持以上技术的web浏览器作为运行平台。这些浏览器目前包括:Mozilla、Firefox、Internet Explorer、Opera、Konqueror及Safari。但是Opera不支持XSL格式对象,也不支持XSLT。
优点和缺点
传统的web应用允许用户填写表单(form),当提交表单时就向web服务器发送一个请求。服务器接收并处理传来的表单,然後返回一个新的网页。这个做法浪费了许多带宽,因为在前後两个页面中的大部分HTML代码往往是相同的。由于每次应用的交互都需要向服务器发送请求,应用的响应时间就依赖于服务器的响应时间。这导致了用户界面的响应比本地应用慢得多。
与此不同,AJAX应用可以仅向服务器发送并取回必需的数据,它使用SOAP或其它一些基于 XML的web service接口,并在客户端采用JavaScript处理来自服务器的响应。因为在服务器和浏览器之间交换的数据大量减少,结果我们就能看到响应更快的应用。同时很多的处理工作可以在发出请求的客户端机器上完成,所以Web服务器的处理时间也减少了。
使用Ajax的最大优点,就是能在不更新整个页面的前提下维护数据。这使得Web应用程序更为迅捷地回应用户动作,并避免了在网络上发送那些没有改变过的信息。
Ajax不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。就像 DHTML应用程序那样,Ajax应用程序必须在众多不同的浏览器和平台上经过严格的测试。随着Ajax的成熟,一些简化Ajax使用方法的程序库也相继问世。同样,也出现了另一种辅助程序设计的技术,为那些不支持JavaScript的用户提供替代功能。
对应用Ajax最主要的批评就是,它可能破坏浏览器后退按钮的正常行为[4]。在动态更新页面的情况下,用户无法回到前一个页面状态,这是因为浏览器仅能记下历史记录中的静态页面。一个被完整读入的页面与一个已经被动态修改过的页面之间的差别非常微妙;用户通常都希望单击后退按钮,就能够取消他们的前一次操作,但是在Ajax应用程序中,却无法这样做。不过开发者已想出了种种办法来解决这个问题,当中大多数都是在用户单击后退按钮访问历史记录时,通过建立或使用一个隐藏的IFRAME来重现页面上的变更。(例如,当用户在Google Maps中单击后退时,它在一个隐藏的IFRAME中进行搜索,然后将搜索结果反映到Ajax元素上,以便将应用程序状态恢复到当时的状态。)
一个相关的观点认为,使用动态页面更新使得用户难于将某个特定的状态保存到收藏夹中。该问题的解决方案也已出现,大部分都使用URL片断标识符(通常被称为锚点,即URL中#后面的部分)来保持跟踪,允许用户回到指定的某个应用程序状态。(许多浏览器允许JavaScript动态更新锚点,这使得Ajax应用程序能够在更新显示内容的同时更新锚点。)这些解决方案也同时解决了许多关于不支持后退按钮的争论。
进行Ajax开发时,网络延迟——即用户发出请求到服务器发出响应之间的间隔——需要慎重考虑。不给予用户明确的回应 [5],没有恰当的预读数据 [6],或者对XMLHttpRequest的不恰当处理[7],都会使用户感到延迟,这是用户不欲看到的,也是他们无法理解的[8]。通常的解决方案是,使用一个可视化的组件来告诉用户系统正在进行后台操作并且正在读取数据和内容。
基础应用
创建XMLHttpRequest 方法如下
XMLHttpRequest 类首先由Internet Explorer以ActiveX对象引入,被称为XMLHTTP。 后来Mozilla﹑Netscape﹑Safari 和其他浏览器也提供了XMLHttpRequest类,不过它们创建XMLHttpRequest类的方法不同。
对于Internet Explorer浏览器:
xmlhttp_request = new ActiveXObject("Msxml2.XMLHTTP.3.0"); //3.0或4.0, 5.0
xmlhttp_request = new ActiveXObject("Msxml2.XMLHTTP");
xmlhttp_request = new ActiveXObject("Microsoft.XMLHTTP");
由于在不同Internet Explorer浏览器中XMLHTTP版本可能不一致,为了更好的兼容不同版本的Internet Explorer浏览器,因此我们需要根据不同版本的Internet Explorer浏览器来创建XMLHttpRequest类,上面代码就是根据不同的Internet Explorer浏览器创建XMLHttpRequest类的方法。
对于Mozilla﹑Netscape﹑Safari等浏览器
创建XMLHttpRequest 方法如下:xmlhttp_request = new XMLHttpRequest();
如果服务器的响应没有XML mime-type header,某些Mozilla浏览器可能无法正常工作。 为了解决这个问题,如果服务器响应的header不是text/xml,可以调用其它方法修改该header。
xmlhttp_request = new XMLHttpRequest();
xmlhttp_request.overrideMimeType('text/xml');
在实际应用中,为了兼容多种不同版本的浏览器,一般将创建XMLHttpRequest类的方法写成如下形式:
try{
if( window.ActiveXObject ){
for( var i = 5; i; i-- ){
try{
if( i == 2 ){
xmlhttp_request = new ActiveXObject( "Microsoft.XMLHTTP" ); }
else{
xmlhttp_request = new ActiveXObject( "Msxml2.XMLHTTP." + i + ".0" );
xmlhttp_request.setRequestHeader("Content-Type","text/xml");
xmlhttp_request.setRequestHeader("Charset","gb2312"); }
break;}
catch(e){
xmlhttp_request = false; } } }
else if( window.XMLHttpRequest )
{ xmlhttp_request = new XMLHttpRequest();
if (xmlhttp_request.overrideMimeType)
{ xmlhttp_request.overrideMimeType('text/xml'); } } }
catch(e){ xmlhttp_request = false; }
发送请求了
可以调用HTTP请求类的open()和send()方法,如下所示:
xmlhttp_request.open('GET', URL, true);
xmlhttp_request.send(null);
open()的第一个参数是HTTP请求方式—GET,POST或任何服务器所支持的您想调用的方式。 按照HTTP规范,该参数要大写;否则,某些浏览器(如Firefox)可能无法处理请求。
第二个参数是请求页面的URL。
第三个参数设置请求是否为异步模式。如果是TRUE,JavaScript函数将继续执行,而不等待服务器响应。这就是"AJAX"中的"A"。
服务器的响应
这需要告诉HTTP请求对象用哪一个JavaScript函数处理这个响应。可以将对象的onreadystatechange属性设置为要使用的JavaScript的函数名,如下所示:
xmlhttp_request.onreadystatechange =FunctionName;
FunctionName是用JavaScript创建的函数名,注意不要写成FunctionName(),当然我们也可以直接将JavaScript代码创建在onreadystatechange之后,例如:
xmlhttp_request.onreadystatechange = function(){
// JavaScript代码段
};
首先要检查请求的状态。只有当一个完整的服务器响应已经收到了,函数才可以处理该响应。XMLHttpRequest 提供了readyState属性来对服务器响应进行判断。
readyState的取值如下:
0 (未初始化)
1 (正在装载)
2 (装载完毕)
3 (交互中)
4 (完成)
所以只有当readyState=4时,一个完整的服务器响应已经收到了,函数才可以处理该响应。具体代码如下:
if (http_request.readyState == 4) { // 收到完整的服务器响应 }
else { // 没有收到完整的服务器响应 }
当readyState=4时,一个完整的服务器响应已经收到了,接着,函数会检查HTTP服务器响应的状态值。完整的状态取值可参见W3C文档。当HTTP服务器响应的值为200时,表示状态正常。
处理从服务器得到的数据
有两种方式可以得到这些数据:
(1) 以文本字符串的方式返回服务器的响应
(2) 以XMLDocument对象方式返回响应
ScriptManager控件
ScriptManager控件包括在ASP.NET 2.0 AJAX Extensions中,它用来处理页面上的所有组件以及页面局部更新,生成相关的客户端代理脚本以便能够在JavaScript中访问Web Service,所有需要支持ASP.NET AJAX的ASP.NET页面上有且只能有一个ScriptManager控件。在ScriptManager控件中我们可以指定需要的脚本库,或者指定通过JS来调用的Web Service,以及调用AuthenticationService和ProfileService,还有页面错误处理等。
主要内容
1.控件概述
2.一个简单的示例
3.客户端脚本模式
4.错误处理
5.Services属性
6.Scripts属性
一.控件概述
ScriptManager控件包括在ASP.NET 2.0 AJAX Extensions中,它用来处理页面上的所有组件以及页面局部更新,生成相关的客户端代理脚本以便能够在JavaScript中访问Web Service,所有需要支持ASP.NET AJAX的ASP.NET页面上有且只能有一个ScriptManager控件。在ScriptManager控件中我们可以指定需要的脚本库,或者指定通过JS来调用的Web Service,还可以指定页面错误处理等。
使用<asp:ScriptManager/>来定义一个ScriptManager,简单的ScriptManager定义形式:
runat ="server" >
< AuthenticationService Path ="" />
< ProfileService LoadProperties ="" Path ="" />
< Scripts >
<asp:ScriptReference/>
</ Scripts >
< Services >
< asp:ServiceReference />
</ Services >
</ asp:ScriptManager >
ScriptManager
属性/方法 | 描述 |
AllowCustomError | 和Web.config中的自定义错误配置区<customErrors>相联系,是否使用它,默认值为true |
AsyncPostBackErrorMessage | 异步回传发生错误时的自定义提示错误信息, |
AsyncPostBackTimeout | 异步回传时超时限制,默认值为90,单位为秒 |
EnablePartialRendering | 是否支持页面的局部更新,默认值为True,一般不需要修改 |
ScriptMode | 指定ScriptManager发送到客户端的脚本的模式,有四种模式:Auto,Inherit,Debug,Release,默认值为Auto,后面会仔细说到。 |
ScriptPath | 设置所有的脚本块的根目录,作为全局属性,包括自定义的脚本块或者引用第三方的脚本块。如果在Scripts中的<asp:ScriptReference/>标签中设置了Path属性,它将覆盖该属性。 |
OnAsyncPostBackError | 异步回传发生异常时的服务端处理函数,在这里可以捕获一场信息并作相应的处理。 |
OnResolveScriptReference | 指定ResolveScriptReference事件的服务器端处理函数,在该函数中可以修改某一条脚本的相关信息如路径、版本等。 |
二.一个简单的示例
这个例子其实是UpdatePanel示例,在页面中加入了日期控件和一个下拉框,根据下拉框选择的不同,日期控件背景变为不同的颜色。示例代码如下:
< script runat ="server" >
void DropDownSelection_Change(Object sender, EventArgs e)
{
Calendar1.DayStyle.BackColor =
System.Drawing.Color.FromName(ColorList.SelectedItem.Value);
}
</ script >
< html xmlns ="http://www.w3.org/1999/xhtml" >
< head id ="Head1" runat ="server" >
< title > ScriptManager Example </ title >
</ head >
< body >
< form id ="form1" runat ="server" >
< div >
< asp:ScriptManager ID ="ScriptManager1"
runat ="server" >
</ asp:ScriptManager >
< asp:UpdatePanel ID ="UpdatePanel1"
runat ="server" >
< ContentTemplate >
< asp:Calendar ID ="Calendar1"
ShowTitle ="True"
runat ="server" />
< div >
Background:
< br />
< asp:DropDownList ID ="ColorList"
AutoPostBack ="True"
OnSelectedIndexChanged ="DropDownSelection_Change"
runat ="server" >
< asp:ListItem Selected ="True" Value ="White" >
White </ asp:ListItem >
< asp:ListItem Value ="Silver" >
Silver </ asp:ListItem >
< asp:ListItem Value ="DarkGray" >
Dark Gray </ asp:ListItem >
< asp:ListItem Value ="Khaki" >
Khaki </ asp:ListItem >
< asp:ListItem Value ="DarkKhaki" > D
ark Khaki </ asp:ListItem >
</ asp:DropDownList >
</ div >
</ ContentTemplate >
</ asp:UpdatePanel >
< br />
</ div >
</ form >
</ body >
</ html >
三.客户端脚本模式
在前面我们提到了ScriptMode属性指定ScriptManager发送到客户端的脚本的模式,它有四种模式:Auto,Inherit,Debug,Release,默认值为Auto。
1.Auto:它会根据Web站点的Web.config配置文件来决定使用哪一种模式,只有当配置文件中retail属性设置为false:
< deployment retail ="false" />
</ system.web >
或者页面中的Debug指令设为true的时候会使用Debug版本,其他的情况都会使用Release版本。
AutoEventWireup ="true" CodeFile ="Default.aspx.cs" Inherits ="_Default" % >
2.Inherit:应该是通过程序设置ScriptMode的时候,等同于Auto?(不太了解)
3.Debug:客户端脚本使用Debug版本,除非retail属性设为true。
4.Release:客户端脚本使用Release版本,除非retail属性设为false。
四.错误处理
在页面回传时如果发生了异常AsyncPostBackError事件将被触发,错误信息的处理依赖于AllowCustomErrors属性、AsyncPostBackErrorMessage属性和Web.config中的<customErrors>配置区。下面看一个简单的错误处理例子,在AsyncPostBackError事件中捕获到异常信息并设置AsyncPostBackErrorMessage属性。
< script runat ="server" >
protected void ErrorProcessClick_Handler(object sender, EventArgs e)
{
// This handler demonstrates an error condition. In this example
// the server error gets intercepted on the client and an alert is shown.
throw new ArgumentException();
}
protected void SuccessProcessClick_Handler(object sender, EventArgs e)
{
// This handler demonstrates no server side exception.
UpdatePanelMessage.Text = "The asynchronous postback completed successfully.";
}
protected void ScriptManager1_AsyncPostBackError(object sender, AsyncPostBackErrorEventArgs e)
{
ScriptManager1.AsyncPostBackErrorMessage = "异常信息为:" + e.Exception.Message;
}
</ script >
< html xmlns ="http://www.w3.org/1999/xhtml" >
< head id ="Head1" runat ="server" >
< title > PageRequestManager endRequestEventArgs Example </ title >
< style type ="text/css" >
body {
font-family: Tahoma;
}
#AlertDiv{
left: 40%; top: 40%;
position: absolute; width: 200px;
padding: 12px;
border: #000000 1px solid;
background-color: white;
text-align: left;
visibility: hidden;
z-index: 99;
}
#AlertButtons{
position: absolute;
right: 5%;
bottom: 5%;
}
</ style >
</ head >
< body id ="bodytag" >
< form id ="form1" runat ="server" >
< div >
< asp:ScriptManager ID ="ScriptManager1" runat ="server"
OnAsyncPostBackError ="ScriptManager1_AsyncPostBackError" >
</ asp:ScriptManager >
< script type ="text/javascript" language ="javascript" >
var divElem = 'AlertDiv';
var messageElem = 'AlertMessage';
var errorMessageAdditional = 'Please try again.';
var bodyTag = 'bodytag';
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);
function ToggleAlertDiv(visString)
{
if (visString == 'hidden')
{
$get(bodyTag).style.backgroundColor = 'white';
}
else
{
$get(bodyTag).style.backgroundColor = 'gray';
}
var adiv = $get(divElem);
adiv.style.visibility = visString;
}
function ClearErrorState() {
$get(messageElem).innerHTML = '';
ToggleAlertDiv('hidden');
}
function EndRequestHandler(sender, args)
{
if (args.get_error() != undefined && args.get_error().httpStatusCode == '500')
{
var errorMessage = args.get_error().message
args.set_errorHandled(true);
ToggleAlertDiv('visible');
$get(messageElem).innerHTML = '"' +
errorMessage + '" ' + errorMessageAdditional;
}
}
</ script >
< asp:UpdatePanel runat ="Server" UpdateMode ="Conditional" ID ="UpdatePanel1" >
< ContentTemplate >
< asp:Panel ID ="Panel1" runat ="server" GroupingText ="Update Panel" >
< asp:Label ID ="UpdatePanelMessage" runat ="server" />
< br />
Last update:
<% = DateTime.Now.ToString() %>
.
< br />
< asp:Button runat ="server" ID ="Button1" Text ="Submit Successful Async Postback"
OnClick ="SuccessProcessClick_Handler" OnClientClick ="ClearErrorState()" />
< asp:Button runat ="server" ID ="Button2" Text ="Submit Async Postback With Error"
OnClick ="ErrorProcessClick_Handler" OnClientClick ="ClearErrorState()" />
< br />
</ asp:Panel >
</ ContentTemplate >
</ asp:UpdatePanel >
< div id ="AlertDiv" >
< div id ="AlertMessage" >
</ div >
< br />
< div id ="AlertButtons" >
< input id ="OKButton" type ="button" value ="OK"
runat ="server" onclick ="ClearErrorState()" />
</ div >
</ div >
</ form >
</ body >
</ html >
运行后时界面:
发生异常信息:
五.Services属性
Services用来管理对WebService的调用,通过<asp:ServiceReference>标签可以在Services中注册一个WebService,在运行时ScriptManager将为每一个ServiceReference对象生成一个客户端代理,<asp:ServiceReference>标签一个很重要的属性是Path,用来指定WebService的路径,如下所示:
< Services >
< asp:ServiceReference Path ="Service.asmx" />
</ Services >
</ asp:ScriptManager >
看一个简单的调用WebService的例子:
WebService如下,注意在WebServiceSample上加ScriptService特性:
public class WebServiceSample : System.Web.Services.WebService {
public WebServiceSample()
{
//Uncomment the following line if using designed components
//InitializeComponent();
}
[WebMethod]
public string EchoString(String s)
{
return "Hello " + s;
}
}
ASPX页面:
< html xmlns ="http://www.w3.org/1999/xhtml" >
< head runat ="server" >
< title > Untitled Page </ title >
</ head >
< script type ="text/javascript" language ="JavaScript" >
function OnbuttonGo_click()
{
requestSimpleService = WebServiceSample.EchoString(
document.getElementById('inputName').value, //params
OnRequestComplete //Complete event
);
return false;
}
function OnRequestComplete(result)
{
alert(result);
}
</ script >
< body >
< form id ="form1" runat ="server" >
< asp:ScriptManager ID ="ScriptManager1" runat ="server" >
< Services >
< asp:ServiceReference Path ="WebServiceSample.asmx" />
</ Services >
</ asp:ScriptManager >
< div >
< input type ="text" id ="inputName" size =20 />
< input id ="button" type ="button" value ="调 用" onclick ="return OnbuttonGo_click()" /></ div >
</ form >
</ body >
</ html >
运行后效果如下:
当然了也可以在运行时动态的在Services中加入ServiceReference,下面看一个运行时动态加入ServiceReference的例子:
< script runat ="server" >
void Page_Load(object sender, EventArgs e)
{
ServiceReference sr = new ServiceReference();
sr.Path = "WebServiceSample.asmx";
ScriptManager1.Services.Add(sr);
}
</ script >
< html xmlns ="http://www.w3.org/1999/xhtml" >
< head runat ="server" >
< title > Untitled Page </ title >
</ head >
< script type ="text/javascript" language ="JavaScript" >
function OnbuttonGo_click()
{
requestSimpleService = WebServiceSample.EchoString(
document.getElementById('inputName').value, //params
OnRequestComplete //Complete event
);
return false;
}
function OnRequestComplete(result)
{
alert(result);
}
</ script >
< body >
< form id ="form1" runat ="server" >
< asp:ScriptManager ID ="ScriptManager1" runat ="server" >
</ asp:ScriptManager >
< div >
< input type ="text" id ="inputName" size =20 />
< input id ="button" type ="button" value ="调 用" onclick ="return OnbuttonGo_click()" /></ div >
</ form >
</ body >
</ html >
可以看到运行后和在ScriptManager中直接加入的效果是一样的。
六.Scripts属性
关于Scripts属性到后面具体再说吧,最主要的属性有Path指定脚本的路径,ScriptMode指定客户端脚本的模式,它会覆盖ScriptManager中的ScriptMode属性,还有一个属性是IgnoreScriptPath,指定是否忽略掉ScriptManager中的ScriptPath属性。
关于ScriptManager控件就学习到这里了,至于AuthenticationService属性和ProfileService属性都很简单。