2009年10月13日

来源:互联网 发布:怎样注册域名 编辑:程序博客网 时间:2024/04/30 10:26

ASP.NET AJAX客户端编程之旅(一)——Hello!ASP.NET AJAX

摘要

      本文将首先介绍一下文章的写作背景和用到的相关技术。然后将分别使用朴素的Ajax技术和ASP.NET AJAX框架分别实现经典的“Hello!XX”,通过两个小例子,使朋友们对这个框架的特点和框架的使用方法有一个初步的认识。

 

前言

      我想,如果今天哪个Web开发人员说没有听说过Ajax技术,那实在太不可思议了。确实,近几年,Ajax这个词以超乎想象的速度红遍Web开发领域,大到Google、网易,小到一些地方公司的主页,都普遍开始加入Ajax元素。这种技术,给Web开发带来了革命性的意义,也使得Web产品及B/S系统的用户体验大大改善。

      然而,Ajax用起来华丽、爽快,开发起来却困难重重。JavaScript语言怪异的语法、没有IDE支持以及难以调试,都成为Ajax开发的硬伤。另外B/S系统和C/S不同,浏览器的多样性也给Ajax的开发带来很多困难,使得我们在做Ajax应用时,不得不考虑到各种浏览器的差异,开发过程痛苦至极。

      针对这种情况,各种Ajax框架应运而生。这其中的佼佼者,便是微软推出的ASP.NET AJAX框架。它不仅给使得开发Ajax应用变得容易很多,而且更可以与微软的开发工具无缝集成,给.NET平台的开发人员带来很大方便。

      这一系列文章,就是要介绍这个框架的客户端编程。

 

ASP.NET AJAX能做什么?

      ASP.NET AJAX框架带来的好处和特性实在太多了,这里简要列几条:

      1.扩展了JavaScript语言,增加了面向对象特性。简化了一些DOM操作的语法。

      2.一系列的服务器端控件可以让程序员不编写JS,而仅通过拖控件完成Ajax应用的开发。

      3.开创性的提出了客户端组件、行为组件等概念,并提供了一种类似XML的标签式语言,给Ajax客户端编写带来革命性创新。

      4.完善的代理模型机制,使得开发人员可以在JS中直接调用后台程序,就像在后台调用一样。

      5.各种数据类型的自动转换,特别是对于复杂类型,内置自动序列化和反序列化机制,是的前后台可以直接共用复杂类型,而不必手工转换。

      6.提供了大量的客户端组件,方便程序开发。

      7.屏蔽了浏览器之间的差异,让开发人员可以不再处理那些令人头疼的浏览器差异问题。

 

服务器端编程 VS 客户端编程

      ASP.NET AJAX框架提供了两种开发模型:服务器端编程和客户端编程。前者使用方便,开发人员可以不懂JS和Ajax,而是通过传统的ASP.NET开发方式完成Ajax应用的开发,但是其控制粒度较粗。而后者开发难度相对较大,需要开发人员熟悉JavaScript,并熟悉ASP.NET AJAX提供的各种语法支持及客户端编程模型,但是其控制粒度精细,有利于提高应用的性能和质量。

      本系列文章将重点介绍客户端编程。

 

开始ASP.NET AJAX之旅:让我们一起对ASP.NET AJAX说Hello!

      下面,我将分别用两种方式实现一个最简单的Ajax应用:单击按钮,异步调用后台类中的一个方法,返回一个字符串,显示在页面指定位置,整个过程不刷新页面。其效果图如下:

2009年10月13日 - cruelchen - 好好做人

 

      左图为单击前,右图为单击后。整个过程页面无刷新,所显示的字符串是从后台程序得到的。下面,将用两种方法实现这个小应用。

 

没有ASP.NET AJAX的日子:想说Hello不容易!很难很费力!

      首先,我们不使用任何框架,手工创建这个Ajax应用。

      1.创建工程

      打开VS(我用的是2005),创建一个新的Website,命名为AjaxTest。完成后,添加系统文件夹App_Code。

 

      2.创建后台程序

      下面我们要编写供前台调用的后台程序,这个程序很简单,只需要返回一个字符串。我们在App_Code文件夹下添加一个新的文件Hello.cs,这是个C#类文件,其详细代码如下:

Hello.cs:

 12009年10月13日 - cruelchen - 好好做人using System;

 22009年10月13日 - cruelchen - 好好做人

 32009年10月13日 - cruelchen - 好好做人public class Hello

 42009年10月13日 - cruelchen - 好好做人2009年10月13日 - cruelchen - 好好做人2009年10月13日 - cruelchen - 好好做人{

 52009年10月13日 - cruelchen - 好好做人2009年10月13日 - cruelchen - 好好做人    public Hello() 2009年10月13日 - cruelchen - 好好做人{ }

 62009年10月13日 - cruelchen - 好好做人

 72009年10月13日 - cruelchen - 好好做人    public string SayHello()

 82009年10月13日 - cruelchen - 好好做人2009年10月13日 - cruelchen - 好好做人    2009年10月13日 - cruelchen - 好好做人{

 92009年10月13日 - cruelchen - 好好做人        return "Hello!Ajax";

102009年10月13日 - cruelchen - 好好做人    }

112009年10月13日 - cruelchen - 好好做人}

 

      代码没有什么好解释的,只有一个方法,就是返回“Hello!Ajax”这个字符串。

 

      3.创建后台页面

      只有一个类是不成的,Ajax最终要调用一个页面,所以,这里还需要做一个aspx页面供前台直接调用。在网站工程下新建一个文件Output.aspx,将其中的所有代码都删除,只保留第一行。因为我们不需要完整显示这个页面,只是要它返回一行字符串。

Output.aspx:

12009年10月13日 - cruelchen - 好好做人2009年10月13日 - cruelchen - 好好做人< IMG title="2009年10月13日 - cruelchen - 好好做人" alt="2009年10月13日 - cruelchen - 好好做人" src="http://www.cnblogs.com/Images/dot.gif" border="0" >@ Page Language="C#" AutoEventWireup="true" CodeFile="Output.aspx.cs" Inherits="Output" %<

 

      然后,我们需要在这个页面的Page_Load事件中调用Hello类的SayHello方法,并使用Response.Write方法将其输出。

Output.aspx.cs:

 12009年10月13日 - cruelchen - 好好做人using System;

 22009年10月13日 - cruelchen - 好好做人using System.Data;

 32009年10月13日 - cruelchen - 好好做人using System.Configuration;

 42009年10月13日 - cruelchen - 好好做人using System.Collections;

 52009年10月13日 - cruelchen - 好好做人using System.Web;

 62009年10月13日 - cruelchen - 好好做人using System.Web.Security;

 72009年10月13日 - cruelchen - 好好做人using System.Web.UI;

 82009年10月13日 - cruelchen - 好好做人using System.Web.UI.WebControls;

 92009年10月13日 - cruelchen - 好好做人using System.Web.UI.WebControls.WebParts;

102009年10月13日 - cruelchen - 好好做人using System.Web.UI.HtmlControls;

112009年10月13日 - cruelchen - 好好做人

122009年10月13日 - cruelchen - 好好做人public partial class Output : System.Web.UI.Page

132009年10月13日 - cruelchen - 好好做人2009年10月13日 - cruelchen - 好好做人2009年10月13日 - cruelchen - 好好做人{

142009年10月13日 - cruelchen - 好好做人    protected void Page_Load(object sender, EventArgs e)

152009年10月13日 - cruelchen - 好好做人2009年10月13日 - cruelchen - 好好做人    2009年10月13日 - cruelchen - 好好做人{

162009年10月13日 - cruelchen - 好好做人        Hello myHello = new Hello();

172009年10月13日 - cruelchen - 好好做人        Response.Write(myHello.SayHello());

182009年10月13日 - cruelchen - 好好做人    }

192009年10月13日 - cruelchen - 好好做人}

 

      4.编写JavaScript脚本

      我们的主角终于要登场了。让我们开始编写Ajax代码。首先在网站工程下新建ajax.js文件,这个文件将包含Ajax核心代码,具体内容如下:

ajax.js:

 12009年10月13日 - cruelchen - 好好做人var xmlHttp;//全局XMLHttpResquest对象

 22009年10月13日 - cruelchen - 好好做人

 32009年10月13日 - cruelchen - 好好做人//针对不同浏览器,获取XMLHttpRequest对象

 42009年10月13日 - cruelchen - 好好做人function CreateXMLHttpRequest()

 52009年10月13日 - cruelchen - 好好做人2009年10月13日 - cruelchen - 好好做人2009年10月13日 - cruelchen - 好好做人{

 62009年10月13日 - cruelchen - 好好做人    if(window.ActiveXObject)

 72009年10月13日 - cruelchen - 好好做人2009年10月13日 - cruelchen - 好好做人    2009年10月13日 - cruelchen - 好好做人{

 82009年10月13日 - cruelchen - 好好做人        xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");

 92009年10月13日 - cruelchen - 好好做人    }

102009年10月13日 - cruelchen - 好好做人    else

112009年10月13日 - cruelchen - 好好做人2009年10月13日 - cruelchen - 好好做人    2009年10月13日 - cruelchen - 好好做人{

122009年10月13日 - cruelchen - 好好做人        xmlHttp=new XMLHttpResquest();

132009年10月13日 - cruelchen - 好好做人    }

142009年10月13日 - cruelchen - 好好做人}

152009年10月13日 - cruelchen - 好好做人

162009年10月13日 - cruelchen - 好好做人//单击btnSayHello时调用的JS函数

172009年10月13日 - cruelchen - 好好做人function btnSayHello_onClick()

182009年10月13日 - cruelchen - 好好做人2009年10月13日 - cruelchen - 好好做人2009年10月13日 - cruelchen - 好好做人{

192009年10月13日 - cruelchen - 好好做人    CreateXMLHttpRequest();

202009年10月13日 - cruelchen - 好好做人    xmlHttp.onreadystatechange=HandleStateChange;

212009年10月13日 - cruelchen - 好好做人    xmlHttp.open("POST","Output.aspx",true);

222009年10月13日 - cruelchen - 好好做人    xmlHttp.send(null);

232009年10月13日 - cruelchen - 好好做人}

242009年10月13日 - cruelchen - 好好做人

252009年10月13日 - cruelchen - 好好做人//回调函数

262009年10月13日 - cruelchen - 好好做人function HandleStateChange()

272009年10月13日 - cruelchen - 好好做人2009年10月13日 - cruelchen - 好好做人2009年10月13日 - cruelchen - 好好做人{

282009年10月13日 - cruelchen - 好好做人    if(xmlHttp.readyState==4)

292009年10月13日 - cruelchen - 好好做人2009年10月13日 - cruelchen - 好好做人    2009年10月13日 - cruelchen - 好好做人{

302009年10月13日 - cruelchen - 好好做人        if(xmlHttp.status==200)

312009年10月13日 - cruelchen - 好好做人2009年10月13日 - cruelchen - 好好做人        2009年10月13日 - cruelchen - 好好做人{

322009年10月13日 - cruelchen - 好好做人            document.getElementById("result").innerHTML = xmlHttp.responseText;

332009年10月13日 - cruelchen - 好好做人        }

342009年10月13日 - cruelchen - 好好做人    }

352009年10月13日 - cruelchen - 好好做人}

 

      下面我对这个代码进行一个简要的解释。

      首先,xmlHttp是一个全局变量,它被初始化后,将负责整个Ajax应用的核心。CreateXMLHttpRequest方法用来得到XMLHttpRequest对象的实例,这里我们注意到,由于不同浏览器的获取对象方法不同,这里首先要检测浏览器类型,然后使用相应方法获得对象,十分麻烦。btnSayHello_onClick是一个核心函数,当按钮被单击时,将调用这个函数。它首先初始化xmlHttp,然后指定回调函数为HandleStateChange,最后异步发布POST请求,调用Output.aspx页面。最后,HandleStateChange作为回调函数,在xmlHttp的请求状态发生改变时将自动被调用。而在这个函数中,当状态正常时,将id为“result”的DIV的内容设为调用结果。即Output.aspx输出的字符串。

 

      5.主页

      最后,当然我们要制作主要页面。在这里我直接使用Default.aspx,其代码如下:

Defualt.aspx:

 12009年10月13日 - cruelchen - 好好做人2009年10月13日 - cruelchen - 好好做人< IMG title="2009年10月13日 - cruelchen - 好好做人" alt="2009年10月13日 - cruelchen - 好好做人" src="http://www.cnblogs.com/Images/dot.gif" border="0" >@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %<

 22009年10月13日 - cruelchen - 好好做人

 32009年10月13日 - cruelchen - 好好做人

 42009年10月13日 - cruelchen - 好好做人

 52009年10月13日 - cruelchen - 好好做人

 62009年10月13日 - cruelchen - 好好做人

 72009年10月13日 - cruelchen - 好好做人    

 82009年10月13日 - cruelchen - 好好做人< ><  type="text/javascript">

 92009年10月13日 - cruelchen - 好好做人

102009年10月13日 - cruelchen - 好好做人

112009年10月13日 - cruelchen - 好好做人    

122009年10月13日 - cruelchen - 好好做人    

132009年10月13日 - cruelchen - 好好做人        

142009年10月13日 - cruelchen - 好好做人        

152009年10月13日 - cruelchen - 好好做人    

162009年10月13日 - cruelchen - 好好做人    

172009年10月13日 - cruelchen - 好好做人

182009年10月13日 - cruelchen - 好好做人

 

      这里将ajax.js作为外部脚本引入,让后让btnSayHello的onclick事件与btnSayHello_onClick关联。而result这个DIV则用于显示结果。

      现在运行Default.aspx,点击SayHello按钮,即可看到效果。

 

使用ASP.NET AJAX:让Hello说的轻松一点

      可以看出,在上面的实现过程中,JS脚本非常麻烦,不仅要处理各种浏览器的差别(其实我上面的代码还没有照顾到所有浏览器),还要在回调函数中判断相应状态。调用过程也必须手工进行。那么,我们可不可以在JS中直接调用后台代码中的某个方法呢?就像在后台调用一样。答案是肯定的,只要我们使用ASP.NET AJAX。

      ASP.NET AJAX框架在VS2008中是自带的,但如果你和我一样使用的是VS2005和.net framework2.0和话,则需要手工安装。在微软官方网站有下载,安装过程也和普通软件安装很相似,这里不再赘述。

      下面,我们使用ASP.NET AJAX框架再次实现这个应用。

      1.创建工程

      这一次,我们还是需要创建一个新的网站,不同的是,我们选择ASP.NET AJAX-Enabled Web Site,使用这个项目创建网站后,VS将自动在Web.config中配置好这个框架需要的配置项,而且会在页面中自动加入一个ScriptManager控件,这个控件是ASP.NET AJAX应用所必不可少的。创建完成后,仍需要新建App_Code文件夹。

 

      2.创建后台程序

      这个和上一部分的后台程序非常类似,仍是在App_Code文件夹下建立Hello.cs,代码如下:

Hello.cs:

 12009年10月13日 - cruelchen - 好好做人using System;

 22009年10月13日 - cruelchen - 好好做人

 32009年10月13日 - cruelchen - 好好做人public class Hello

 42009年10月13日 - cruelchen - 好好做人2009年10月13日 - cruelchen - 好好做人2009年10月13日 - cruelchen - 好好做人{

 52009年10月13日 - cruelchen - 好好做人2009年10月13日 - cruelchen - 好好做人    public Hello() 2009年10月13日 - cruelchen - 好好做人{ }

 62009年10月13日 - cruelchen - 好好做人

 72009年10月13日 - cruelchen - 好好做人    public string SayHello()

 82009年10月13日 - cruelchen - 好好做人2009年10月13日 - cruelchen - 好好做人    2009年10月13日 - cruelchen - 好好做人{

 92009年10月13日 - cruelchen - 好好做人        return "Hello!ASP.NET AJAX";

102009年10月13日 - cruelchen - 好好做人    }

112009年10月13日 - cruelchen - 好好做人}

 

      3.创建WebService

      其实,使用ASP.NET AJAX框架后,JS是可以直接调用后台类中的方法的,但是这里不建议这样做,而是使用WebService作为过渡,让JS调用WebService。关于其中的理由,将在以后介绍。

      在网站工程下新建WebService文件SayHelloService,这时VS会自动在App_Code文件夹下建立对应的代码文件,SayHelloService.cs,具体程序代码如下:

SayHelloService.cs:

 12009年10月13日 - cruelchen - 好好做人using System;

 22009年10月13日 - cruelchen - 好好做人using System.Web;

 32009年10月13日 - cruelchen - 好好做人using System.Collections;

 42009年10月13日 - cruelchen - 好好做人using System.Web.Services;

 52009年10月13日 - cruelchen - 好好做人using System.Web.Services.Protocols;

 62009年10月13日 - cruelchen - 好好做人using System.Web.Script.Services;

 72009年10月13日 - cruelchen - 好好做人

 82009年10月13日 - cruelchen - 好好做人[WebService(Namespace = "http://tempuri.org/")]

 92009年10月13日 - cruelchen - 好好做人[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]

102009年10月13日 - cruelchen - 好好做人[ScriptService]

112009年10月13日 - cruelchen - 好好做人public class SayHelloService : System.Web.Services.WebService

122009年10月13日 - cruelchen - 好好做人2009年10月13日 - cruelchen - 好好做人2009年10月13日 - cruelchen - 好好做人{

132009年10月13日 - cruelchen - 好好做人2009年10月13日 - cruelchen - 好好做人    public SayHelloService() 2009年10月13日 - cruelchen - 好好做人{ }

142009年10月13日 - cruelchen - 好好做人

152009年10月13日 - cruelchen - 好好做人    [WebMethod]

162009年10月13日 - cruelchen - 好好做人    public string SayHello()

172009年10月13日 - cruelchen - 好好做人2009年10月13日 - cruelchen - 好好做人    2009年10月13日 - cruelchen - 好好做人{

182009年10月13日 - cruelchen - 好好做人        Hello myHello = new Hello();

192009年10月13日 - cruelchen - 好好做人        return myHello.SayHello();

202009年10月13日 - cruelchen - 好好做人    }

212009年10月13日 - cruelchen - 好好做人}

222009年10月13日 - cruelchen - 好好做人

 

      其中要特别注意三个地方,一个是using Web.Script.Services,这里必须引入这个命名空间。然后就是SayHelloService类上面的[ScriptService]属性(Attribute)和SayHello方法上面的[WebMethod]属性,这两个属性对于JS的访问是不可缺少的。

 

      4.编写JavaScript

      这时,ajax.js文件的代码如下:

ajax.js:

 12009年10月13日 - cruelchen - 好好做人//单击btnSayHello时调用的JS函数

 22009年10月13日 - cruelchen - 好好做人function btnSayHello_onClick()

 32009年10月13日 - cruelchen - 好好做人2009年10月13日 - cruelchen - 好好做人2009年10月13日 - cruelchen - 好好做人{

 42009年10月13日 - cruelchen - 好好做人    SayHelloService.SayHello(HandleStateChange);

 52009年10月13日 - cruelchen - 好好做人}

 62009年10月13日 - cruelchen - 好好做人

 72009年10月13日 - cruelchen - 好好做人//回调函数

 82009年10月13日 - cruelchen - 好好做人function HandleStateChange(reusltText)

 92009年10月13日 - cruelchen - 好好做人2009年10月13日 - cruelchen - 好好做人2009年10月13日 - cruelchen - 好好做人{

102009年10月13日 - cruelchen - 好好做人    $get("result").innerHTML=reusltText;

112009年10月13日 - cruelchen - 好好做人}

 

      这里我们看到了神奇的事情:35行JS代码变成了11行,并且这里直接使用了SayHelloService.SayHello()这样的方法,这个方法是定义在SayHelloService.cs里的,而在这里的JS中就像在后台一样,直接调用了这个方法,并不需要创建对象、发送请求等一大套东西。这里也不用担心浏览器差别问题,因为这个框架已经为我们屏蔽了浏览器差异。

      而且回调函数中,不需要判断状态了,因为ASP.NET AJAX自动分开了成功时调用的回调函数和失败时调用的回调函数。而且这里用“$get”代替了“getElementById”,这也是这个框架给我们提供的便利。

 

      5.主页

      现在我们再看看主页代码:

Default.aspx:

 12009年10月13日 - cruelchen - 好好做人2009年10月13日 - cruelchen - 好好做人< IMG title="2009年10月13日 - cruelchen - 好好做人" alt="2009年10月13日 - cruelchen - 好好做人" src="http://www.cnblogs.com/Images/dot.gif" border="0" >@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %<

 22009年10月13日 - cruelchen - 好好做人

 32009年10月13日 - cruelchen - 好好做人

 42009年10月13日 - cruelchen - 好好做人

 52009年10月13日 - cruelchen - 好好做人

 62009年10月13日 - cruelchen - 好好做人    

 72009年10月13日 - cruelchen - 好好做人

 82009年10月13日 - cruelchen - 好好做人

 92009年10月13日 - cruelchen - 好好做人    

102009年10月13日 - cruelchen - 好好做人        

112009年10月13日 - cruelchen - 好好做人2009年10月13日 - cruelchen - 好好做人            

142009年10月13日 - cruelchen - 好好做人            

152009年10月13日 - cruelchen - 好好做人                

162009年10月13日 - cruelchen - 好好做人            

172009年10月13日 - cruelchen - 好好做人        

182009年10月13日 - cruelchen - 好好做人        

192009年10月13日 - cruelchen - 好好做人            

202009年10月13日 - cruelchen - 好好做人            

212009年10月13日 - cruelchen - 好好做人        

222009年10月13日 - cruelchen - 好好做人    

232009年10月13日 - cruelchen - 好好做人

242009年10月13日 - cruelchen - 好好做人

 

      可以看到,唯一变化就是多了一个ScriptManager控件,这是使用ASP.NET AJAX框架必须引入的控件。控件中还定义了需要引入的外部JS脚本文件和WebService文件。

      现在运行Default.aspx,也达到了同样效果。

 

结束语

      我想通过上面的两个例子,应该能从感性层面上体会到ASP.NET AJAX这个框架的一些特性及优势。当然,其特性还远不止这些,像实体类的自动序列化和反序列化、客户端组件等一系列内容,将在后续章节讨论。

      这里也没有对技术进行细致讲解,意在使朋友们将注意力集中在对这个框架的感性理解上。后续文章会对一些技术性问题进行讲述。

      文中的两个小例子可以在这里下载:AjaxTest.rar    ASPNETAJAXTest.rar

 

主要参考文献

原创粉丝点击