Chinaunix首页 | 论坛 | 博客
  • 博客访问: 640267
  • 博文数量: 233
  • 博客积分: 2221
  • 博客等级: 大尉
  • 技术积分: 3184
  • 用 户 组: 普通用户
  • 注册时间: 2010-02-16 14:01
个人简介

瓜瓜派的瓜瓜

文章分类

全部博文(233)

文章存档

2013年(28)

2012年(197)

2011年(8)

分类: IT业界

2012-01-09 18:54:42

  •    
  •    
  •    
  •    
  •    
  •    
  •    
  •    
  •    
  •         11月21日晚7点应邀在武汉大学信息学院做了一场关于ASP.NETAJAX开发的报告,以我自己经历讲述了一些特殊应用在过去到现在实现手段的变化,本来想回家之后做个总结的,但是由于最近以来事情一直很多,所以没有来得及总结。今晚得以有空总结一下。
    AJAX介绍
    其实AJAX应用的核心就是XMLHttpRequest,通过现象看本质,即使使用微软的AJAX服务器控件最终也是需要这些的,只不过使用微软AJAX服务器控件开发AJAX应用时我们不需要关心JS脚本的实现,只需关心业务逻辑就可以了,因而可以简化开发和提高开发速度。AJAX的基础是XHTMLCSSDOMJavaScriptXMLXMLHttpRequest
    正确使用AJAX技术可以改善用户体验,是用户与服务器的交互更流畅,某些情况下还能减少服务器流量。在以前AJAX只是作为一种比较炫的技术为一些大型网站所使用,现今这个比云计算还要流行了,至少云计算更多地还是停留在人们的概念里,而AJAX确确实实应用在WEB开发当中了。WEB开发人员的招聘都是言必精通AJAX技术。
    下面分别讲讲在ASP.NET开发中可以供选择的开发AJAX应用的方式:
    采用纯JavaScript实现
    在武侠小说中绝顶高手飞花摘叶都可以伤人,在WEB开发领域真正的高手也可以无需借助任何其它库就可以开发出AJAX应用。不适用任何第三方库开发AJAX应用就需要自己区分浏览器来实例化XMLHttpRequest对象实例,下面的代码是一个简单的调用AJAX的代码:

    • xmlns=""
      >
    •     获取服务器时间的例子
    •     language="javascript"
      type="text/javascript">
    • border="0">
    •    
    服务器时间id="time">
    type="button"
    value="完整时间"
    onclick="javascript:void getServerTime('yyyy-mm-dd hh:mm:ss');"
    />
    type="button"
    value="年月日"
    onclick="javascript:void getServerTime('yyyy-MM-dd');"
    />
    type="button"
    value="时分秒"
    onclick="javascript:void getServerTime('hh:mm:ss');"
    />
    type="button"
    value="月份日期"
    onclick="javascript:void getServerTime('mm-dd');"
    />


  • 获取服务器时间的例子
    服务器时间
     
    注意XMLHttpRequest.readyState共有5种状态,其可能值和对应描述如下:
    0:请求未初始化,还没有调用 open()

    1:请求已经建立,但是还没有发送,还没有调用 send()

    2:请求已发送,正在处理中(通常现在可以从响应中获取内容头)。

    3:请求在处理中;通常响应中已有部分数据可用了,没有全部完成。
    4:响应已完成;您可以获取并使用服务器的响应了。


    从上面的代码中可以看出每次实例化XMLHttpRequest对象都需要判断,一些常用的操作也可以封装一下,利用Prototype这个JavaScript脚本库就可以轻松做到这一点,实际上早期很多人就用到了Prototype来开发AJAX应用,并且在Prototype中还封装了其它很多通用的方法,大大提高了我们的开发效率。
    使用Prototype
    Prototype中提供了一个Ajax对象,这样开发人员就可以直接使用Ajax对象而不必考虑如何判断浏览器类型再决定如何实例化XMLHttpRequest对象的实例了。下面的代码是使用了Protype之后的代码:


    • xmlns="">
    •     使用Prototype获取服务器时间的例子
    •     type="text/javascript"
      language="javascript"
      src="prototype.js"
      mce_src="prototype.js">
    •     language="javascript"
      type="text/javascript">
    • border="0">
    •    
    •     服务器时间id="time">
  •    
  •    
  •     type="button"
    value="完整时间"
    onclick="javascript:void getServerTime('yyyy-mm-dd hh:mm:ss');"
    />type="button"
    value="年月日"
    onclick="javascript:void getServerTime('yyyy-MM-dd');"
    />
  •    
  •    
  •     type="button"
    value="时分秒"
    onclick="javascript:void getServerTime('hh:mm:ss');"
    />type="button"
    value="月份日期"
    onclick="javascript:void getServerTime('mm-dd');"
    />
  •    
  •    


  • 使用Prototype获取服务器时间的例子
    服务器时间
     

    从上面的代码可以看出使用了一些相对较为成熟的JavaScript框架之后可以使我们的代码大大减少,开发速度也得到了提高。
    使用jQuery
    当然我们还可以使用目前比较热门的JavaScript框架jQuery,这个在VS2008中需要安装SP1后才能活得智能提示,在VS2010中已经集成了。如果使用jQuery上面的代码可以简化为:


    •        xmlns="">
    •       
    •            使用jQuery获取服务器时间的例子
    •            src="jquery-1.2.6-cn.js"
      mce_src="jquery-1.2.6-cn.js"
      type="text/javascript">
    •     type="text/javascript"
      language="javascript">
    •       
    •       
    •        border="0">
    •            
    •            服务器时间id="time">
  •            
  •            
  •            type="button"
    value="完整时间"
    onclick="javascript:void getServerTime('yyyy-mm-dd hh:mm:ss');"
    />type="button"
    value="年月日"
    onclick="javascript:void getServerTime('yyyy-MM-dd');"
    />
  •            
  •            
  •            type="button"
    value="时分秒"
    onclick="javascript:void getServerTime('hh:mm:ss');"
    />type="button"
    value="月份日期"
    onclick="javascript:void getServerTime('mm-dd');"
    />
  •            
  •            
  •       


  • 使用jQuery获取服务器时间的例子 服务器时间
     

    可以看出在jQuery中提供了更多、更灵活的处理AJAXXHTML的方法,简易大家都去了解一下。
    在上面的方式中无论使用自己写全部JavaScript脚本还是利用Protype或者jQuery这类框架的方式,都是需要写一些JS脚本的,有没有尽可能少写脚本的方式呢?毕竟我们知道JS脚本调试起来相对较为困难些。答案是有的,那就是使用AjaxPro
    使用AjaxPro
    下面是一个使用AjaxPro的例子,设计代码如下:

    •        xmlns="">
    •       
    •            使用jQuery获取服务器时间的例子
    •            src="jquery-1.2.6-cn.js"
      mce_src="jquery-1.2.6-cn.js"
      type="text/javascript">
    •     type="text/javascript"
      language="javascript">
    •       
    •       
    •        border="0">
    •            
    •            服务器时间id="time">
  •            
  •            
  •            type="button"
    value="完整时间"
    onclick="javascript:void getServerTime('yyyy-mm-dd hh:mm:ss');"
    />type="button"
    value="年月日"
    onclick="javascript:void getServerTime('yyyy-MM-dd');"
    />
  •            
  •            
  •            type="button"
    value="时分秒"
    onclick="javascript:void getServerTime('hh:mm:ss');"
    />type="button"
    value="月份日期"
    onclick="javascript:void getServerTime('mm-dd');"
    />
  •            
  •            
  •       


  • 使用jQuery获取服务器时间的例子 服务器时间
     后台逻辑代码如下:


    • using System;  
    • using System.Data;  
    • using System.Configuration;  
    • using System.Collections;  
    • using System.Web;  
    • using System.Web.Security;  
    • using System.Web.UI;  
    • using System.Web.UI.WebControls;  
    • using System.Web.UI.WebControls.WebParts;  
    • using System.Web.UI.HtmlControls;  
    • using System.Text;  
    • public partial class AjaxPager : System.Web.UI.Page  
    • {  
    •     protected
      void Page_Load(object sender, EventArgs e)  
    •     {  
    •         if (Cache["Data"] == null)  
    •         {  
    •             InitData();  
    •         }  
    •         AjaxPro.Utility.RegisterTypeForAjax(typeof(AjaxPager));  
    •     }  
    •     ///
    •     /// 从数据库中指定位置读取指定数目的数据
    •     ///
    •     /// 记录的起始位置
    •     /// 要读取的记录条数
    •     ///
    •     [AjaxPro.AjaxMethod]  
    •     public DataTable GetDataTable(int startIndex, int size)  
    •     {  
    •         DataTable source = (DataTable)Cache["Data"];  
    •         DataTable tempData = new DataTable();  
    •         int j = 0;  
    •         for (int i = startIndex; i < source.Rows.Count && j < size; i++, j++)  
    •         {  
    •             tempData.Rows.Add(source.Rows);  
    •         }  
    •         return tempData;  
    •     }  
    •     ///
    •     /// 传递div节点的html字符串
    •     ///
    •     ///
    •     ///
    •     ///
    •     [AjaxPro.AjaxMethod]  
    •     public
      string GetString(int startIndex, int size)  
    •     {  
    •         StringBuilder text = new StringBuilder();  
    •         text.Append("");  
    •         text.Append("
    • ");  
    •         text.Append("
    • ");  
    •         text.Append("
    • ");  
    •         text.Append("
    • ");  
    •         text.Append("
    • ");  
    •         text.Append("
    • ");  
    •         text.Append("
    • ");  
    •         text.Append("
    • ");  
    •         DataTable source = (DataTable)Cache["Data"];  
    •         int j = 0;  
    •         DataRow row;  
    •         for (int i = startIndex; i < source.Rows.Count && j < size; i++, j++)  
    •         {  
    •             row = source.Rows;  
    •             for (int column = 0; column < source.Columns.Count; column++)  
    •             {  
    •                 text.Append("
    • ");  
    •                 text.Append("
    • ");  
    •                 text.Append("
    • ");  
    •             }  
    •             //tempData.Rows.Add(source.Rows);
    •         }  
    •         return text.ToString();  
    •     }  
    •     ///
    •     /// 返回记录总条数
    •     ///
    •     ///
    •     [AjaxPro.AjaxMethod]  
    •     public
      int GetRecordCount()  
    •     {  
    •         DataTable source = (DataTable)Cache["Data"];  
    •         return source.Rows.Count;  
    •     }  
    •     ///
    •     /// 说明:此处实际情况应该从数据库读取数据,因为本程序主要是演示如何分页的,所以我在这里用程序生成数据
    •     ///
    •     public
      void InitData()  
    •     {  
    •         string firstName = "赵钱孙李周吴郑王冯程诸卫金卫陶姜";  
    •         string lastName = "青雁蓉玲猛勇刚强雪萍";  
    •         Random random = new Random();  
    •         DataTable data = new DataTable();  
    •         data.Columns.Add(new DataColumn("编号", typeof(int)));  
    •         data.Columns.Add(new DataColumn("姓名", typeof(string)));  
    •         data.Columns.Add(new DataColumn("年龄", typeof(int)));  
    •         data.Columns.Add(new DataColumn("性别", typeof(string)));  
    •         data.Columns.Add(new DataColumn("身高", typeof(int)));  
    •         data.Columns.Add(new DataColumn("工资", typeof(int)));  
    •         DataRow row;  
    •         for (int i = 1; i < 100; i++)  
    •         {  
    •             row = data.NewRow();  
    •             row["编号"] = i;  
    •             row["姓名"] = firstName[random.Next(DateTime.Now.Millisecond) % firstName.Length] + lastName[random.Next(DateTime.Now.Millisecond) % lastName.Length];  
    •             row["年龄"] = 10 + random.Next(DateTime.Now.Millisecond) % 30;  
    •             row["性别"] = random.Next(DateTime.Now.Millisecond) % 2 == 0 ? "男" : "女";  
    •             row["身高"] = 150 + random.Next(DateTime.Now.Millisecond) % 50;  
    •             row["工资"] = 1000 + random.Next(DateTime.Now.Millisecond) * 10;  
    •             data.Rows.Add(row);  
    •         }  
    •         Cache["Data"] = data;  
    •     }  
    • }  

    • usingSystem;using System.Data;using System.Configuration;using System.Collections;using System.Web;using System.Web.Security;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.WebControls.WebParts;using System.Web.UI.HtmlControls;using System.Text; public partial class AjaxPager : System.Web.UI.Page{ protected void Page_Load(object sender, EventArgs e) { if(Cache["Data"] == null) { InitData(); }AjaxPro.Utility.RegisterTypeForAjax(typeof(AjaxPager)); } /// /// 从数据库中指定位置读取指定数目的数据 /// ///记录的起始位置 /// 要读取的记录条数 /// [AjaxPro.AjaxMethod] public DataTableGetDataTable(int startIndex, int size) { DataTable source =(DataTable)Cache["Data"]; DataTable tempData = new DataTable(); int j =0; for (int i = startIndex; i < source.Rows.Count && j ); } return tempData;} /// /// 传递div节点的html字符串 /// /// /// /// [AjaxPro.AjaxMethod] public string GetString(int startIndex, int size){ StringBuilder text = new StringBuilder(); text.Append("");text.Append("
      ");text.Append("");text.Append("");text.Append("");text.Append("");text.Append("");text.Append("");text.Append(""); DataTable source =(DataTable)Cache["Data"]; int j = 0; DataRow row; for (int i =startIndex; i < source.Rows.Count && j < size; i++, j++){ row = source.Rows; for (int column = 0; column "); text.Append(""+row[column].ToString()+"");text.Append(""); } //tempData.Rows.Add(source.Rows); }return text.ToString(); } /// /// 返回记录总条数 /// /// [AjaxPro.AjaxMethod] public int GetRecordCount() { DataTable source =(DataTable)Cache["Data"]; return source.Rows.Count; } /// /// 说明:此处实际情况应该从数据库读取数据,因为本程序主要是演示如何分页的,所以我在这里用程序生成数据/// public void InitData() { string firstName ="赵钱孙李周吴郑王冯程诸卫金卫陶姜"; string lastName = "青雁蓉玲猛勇刚强雪萍"; Random random = newRandom(); DataTable data = new DataTable(); data.Columns.Add(newDataColumn("编号", typeof(int))); data.Columns.Add(new DataColumn("姓名",typeof(string))); data.Columns.Add(new DataColumn("年龄", typeof(int)));data.Columns.Add(new DataColumn("性别", typeof(string)));data.Columns.Add(new DataColumn("身高", typeof(int)));data.Columns.Add(new DataColumn("工资", typeof(int))); DataRow row; for(int i = 1; i < 100; i++) { row = data.NewRow(); row["编号"] = i;row["姓名"] = firstName[random.Next(DateTime.Now.Millisecond) %firstName.Length] + lastName[random.Next(DateTime.Now.Millisecond) %lastName.Length]; row["年龄"] = 10 +random.Next(DateTime.Now.Millisecond) % 30; row["性别"] =random.Next(DateTime.Now.Millisecond) % 2 == 0 ? "男" : "女"; row["身高"] =150 + random.Next(DateTime.Now.Millisecond) % 50; row["工资"] = 1000 +random.Next(DateTime.Now.Millisecond) * 10; data.Rows.Add(row); }Cache["Data"] = data; }} 
      从上面的代码中可以看出使用AjaxPro之后可以不用写太多客户端代码,而且不同前面几种做法需要写一个页面调用显示,一个页面负责控制业务逻辑(一般情况下是这样的),使用AjaxPro可以将调用页面和控制业务逻辑页面合在一起,这样服务端代码调试比较方面,而且也不用控制如何发送请求,请求什么时候响应完毕。
      使用AjaxPro有几方面需要注意,就上面的代码中的注意事项说明如下:
      Page_Load事件中:


      JS脚本中:


      网页中调用的服务器端方法:










      使用微软AJAX控件库
      前面几种开发AJAX应用的方式都是遵循一个规律:开发速度是有低到高,开发难易程度由难到易,不过在前面几种方式中不管怎么做都还没有完全脱离JavaScript,这个东东对于现在的一些初学者(就是那些感觉做ASP.NET开发就只是拖拽控件)来说还是有些难度,还是需要写JavaScript来操作HTML页面,为了彻底减轻这部分人掌握ASP.NETAJAX开发,微软推出了AJAX服务器端控件。
      使用微软AJAX服务器端控件可以在做简单设置的情况下满足开发环境中的大部分简单需求,当然做一些稍微复杂点的设置就可以满足开发环境中的绝大部分需求了。
      在微软AJAX服务器控件库中主要有以下几个服务器控件:
      ScriptManager控件:注册脚本,必须在所有服务器控件之前出现
      ScriptManagerProxy控件:参考其它脚本和服务
      UpdatePanel控件:局部刷新控件
      Timer控件:定时执行控件
      UpdateProgress控件:进度显示控件
      下面是一个使用了微软AJAX服务器控件的例子:


      • <%@ Page Language="C#"
        AutoEventWireup="true"
        CodeFile="Register.aspx.cs"
        Inherits="Register" %>
      • xmlns="">
      • runat="server">
      •     用户注册
      •     id="form1"
        runat="server">
      • ID="ScriptManager1"
        runat="server">
      •     border="0">
      •    
    •    
    •    
    •    
    •    
    •    
    •    
    •    
    • 编号姓名年龄性别身高工资
      "+row[column].ToString()+"
      编号姓名年龄性别身高工资
      用户名
    •             ID="UpdatePanel2"
      runat="server">
    •                
    •                     runat="server"
      ID="txtUserName"
      AutoPostBack="True"
    •                         ontextchanged="txtUserName_TextChanged">
    •                     ID="lbStatus"
      runat="server">
    •                
    •                
    •                     ControlID="txtUserName"
      EventName="TextChanged"
      />
    •                
    •             
    •             
    • 密码runat="server"
      ID="txtPwd"
      TextMode="Password">
      确认密码runat="server"
      ID="txtConfirmPwd"
      TextMode="Password">
      找回密码提示问题runat="server"
      ID="txtPwdQuestion">
      找回密码提示答案runat="server"
      ID="txtPwdAnswer">
      籍贯
    •                 ID="UpdatePanel1"
      runat="server">
    •                
    •                 ID="ddlProvince"
      runat="server"
      AppendDataBoundItems="True"
    •                         AutoPostBack="True"
      DataTextField="ProvinceName"
      DataValueField="ProvinceID"
    •                         onselectedindexchanged="ddlProvince_SelectedIndexChanged">
    •                     Value="0">请选择
    •                
    •                 省ID="ddlCity"
      runat="server"
      AutoPostBack="True"
    •                         DataTextField="CityName"
      DataValueField="CityID"
    •                         onselectedindexchanged="ddlCity_SelectedIndexChanged">
    •                
    •                 市ID="ddlRegionalism"
      runat="server"
      AutoPostBack="True"
    •                         DataTextField="RegionalismName"
      DataValueField="RegionalismID">
    •                
    •                 县(区)  
    •                
    •                     
    •                         ControlID="ddlProvince"
    •                             EventName="SelectedIndexChanged"
      />
    •                         ControlID="ddlCity"
    •                             EventName="SelectedIndexChanged"
      />
    •                         ControlID="ddlRegionalism"
    •                             EventName="SelectedIndexChanged"
      />
    •                     
    •                
    •                

    •                 ID="btnRegister"
      runat="server"
      Text="注册"
    •                     onclick="btnRegister_Click"
      />
    •                 id="Reset1"
      type="reset"
      value="reset"
      />
    •    


    <%@Page Language="C#" AutoEventWireup="true" CodeFile="Register.aspx.cs"Inherits="Register" %> 用户注册
    用户名
    密码
    确认密码
    找回密码提示问题
    找回密码提示答案
    籍贯 请选择 县(区)
     



    这个页面的作用其实很简单,就是在用户打开这个注册页面填写完自己的用户名之后准备填写其它信息(就是鼠标从用户名文本框移开后)时就能获知自己的用户名是否已经被注册,还有另外一个效果,就是在用户注册时实现了省(直辖市)、市(区县)、县三级联动的效果,因为使用了微软AJAX控件,所以操作过程中整个页面不会全部刷新,只有局部刷新效果。在使用微软AJAX服务器控件过程中需要注意一些事项,就上面的例子中需要注意的事项如下:




    总结
    其实这篇文章是新瓶装旧酒(和AJAX一样),里面用到的代码都是以前在博客文章中出现的,这篇文章只不过做了一个综合性的比较而已。
    对于上面出现的这么多选择,我们不必一味去追问哪种比哪种一定要好,实际上很多技术都有自己的使用场合的,没有绝对在所有领域所有场合都是最佳的(那就好像找一匹不吃草且跑得快的马)。控制越灵活的需要对脚本知识掌握越高,开发速度也相对低;开发速度越高、调试越容易的控制起来相对较难一些(就像武学一样,绝对高手飞花摘叶可以杀人,花花草草找起来很简单,但是没有深厚的功力不行;倚天屠龙即使在普通人手里也可以让他威力大增,但是不是每个人都有这种机会)。
    对于初学者或者初级开发人员我建议如下:
    如果开发简单AJAX应用,使用AJAX控件首选,无需任何脚本知识;
    如果开发复杂AJAX应用,建议使用jQuery,这是一个可以用于多种动态网页编程的Javascript脚本库。
    阅读(901) | 评论(0) | 转发(0) |
    给主人留下些什么吧!~~