Asp.Net Ajax的两种基本开发模式

引言

最近花了一些时间,将微软Asp.Net官方的Ajax视频全部看了一遍,地址是http://www.asp.net/learn/ajax-videos/,视频大多都很短,8至15分钟的居多,有讲述AjaxControlToolkit中控件用法的,也有讲述Asp.Net Ajax常见的应用场景和技巧的。

本文介绍了使用Asp.Net Ajax做开发时两种最常见的与服务端进行交互(客户端请求服务端执行逻辑,服务端返回结果)的开发模式。第一种我姑且称为UpdatePanel模式,第二种称为Web Service(WCF Service)模式。

开始前的一些准备

对于这些文章,我假设大家都已经安装好了Asp.Net Ajax Extension 和 Asp.Net Ajax Control ToolKit 这两个组件。其中Asp.Net Ajax Extension已经包含在了.Net Framework 3.5中,而Ajax Control Toolkit可以去这个位置下载:http://www.codeplex.com/AjaxControlToolkit/Release/ProjectReleases.aspx?ReleaseId=16488 。因为我使用的是VS2008,所以Ajax Extension无需安装,而Ajax Control Toolkit我安装到了GAC(Global Assembly Cache,全局程序集缓存)中,因此文章所附代码的Bin目录不会包含任何的dll组件。如果你想运行代码,可以像我一样将Ajax Control Toolkit安装到GAC中,或者针对自己的情况(VS2005或者VS2008,私有程序集部署还是GAC部署)对代码进行一些简单的修改和配置。

如果你想安装到GAC中,假设你将AjaxControlToolkit.dll拷贝到了“C:\”下,那么可以打开“VS2008命令提示符”,然后输入下面的命令,按回车:

gacutil -i C:\AjaxControlToolkit.dll

除此以外,还有两点需想要说明。如果你想要在页面的CodeBehind中使用AjaxControlToolkit中定义的类型,那么需要在Web.config中进行一下配置,假设你和我一样采用的是GAC部署,那么Web.Config的设置为:

<system.web>
    <compilation debug="false">
        <assemblies>
            <add assembly="AjaxControlToolkit, Version=3.0.20820.37372, Culture=neutral, PublicKeyToken=28F01B0E84B6D53E"/>
            <!- 其余略 -->
    </compilation>
</system.web>

在VS2008(VS2005)中,你可以将AjaxControlToolkit安装到工具箱(Toolbox)中,但是在安装好以后,当你向页面拖放一个控件时,控件默认的前缀是cc1,并且会在页面顶部自动生成一行控件的声明,类似于这样:

// 自动在页面顶部产生的声明
<%@ Register Assembly="AjaxControlToolkit, Version=3.0.20820.37372, Culture=neutral, PublicKeyToken=28f01b0e84b6d53e" Namespace="AjaxControlToolkit" TagPrefix="cc1" %>
// 页面中控件的样式
<cc1:AutoCompleteExtender> ... </cc1:AutoCompleteExtender>

这样让人感觉页面很不清爽,除此以外,cc1也没有任何的含义。为了解决这个问题,我们也可以在Web.Config进行一下设置:

<system.web>
    <pages>
        <controls>
            <add assembly="AjaxControlToolkit, Version=3.0.20820.37372, Culture=neutral, PublicKeyToken=28f01b0e84b6d53e" namespace="AjaxControlToolkit" tagPrefix="ajaxControlToolkit" />
            <!-- 其余略 -->
        </controls>
    </pages>
<system.web>

如果你和我一样经过上面三个步骤的设置的话,那么在Web站点Bin目录中不会有任何的程序集,另外页面顶部也不会再有控件的声明,同时,拖放控件到页面中时,它的代码将是这样子的:

<ajaxControlToolkit:AutoCompleteExtender> ... </ ajaxControlToolkit:AutoCompleteExtender>

本文以及所有Asp.Net Ajax相关的文章,都假设你采用了和我相同的配置。

Asp.Net Ajax - UpdatePanel模式

现在考虑一个最简单的范例,页面上放置一个Label控件、一个Button控件,当我们点击Button控件的时候,将Label控件的文本更新为当前时间,这里的关键是更新时间的代码位于服务端,而非使用Javascript在客户端来完成。尽管这里服务端的代码仅仅是更新一下时间,但在实际中却可以执行任何的服务端操作。

UpdatePanel是是大家熟悉的一种方式了,即是在页面拖放一个UpdatePanel,将需要用Ajax方式进行更新的控件放在UpdatePanel之内,在本例中是Label控件。可以将Button控件也放置在UpdatePanel之内,也可以不放置。如果UpdatePanel内不放置Button控件,则需要设置UpdatePanel的Triggers节点,其中包括一个ControlID属性和EventName属性,用于指定哪个控件的哪个事件可以触发了一个PostBack。本例中ControlID自然是Button的ID,而EventName则为Click。也就是说当Button的Click事件触发时,进行PostBack操作。下面是aspx页面的主要代码:

<asp:ScriptManager ID="ScriptManager1" runat="server">
 </asp:ScriptManager>

当前时间:
 <asp:UpdatePanel ID="UpdatePanel1" runat="server">
     <ContentTemplate>
         <asp:Label ID="Label1" runat="server" Text="[未设置]"></asp:Label>
     </ContentTemplate>
    <Triggers>
        <asp:AsyncPostBackTrigger ControlID="Button1" EventName="Click" />
     </Triggers>
 </asp:UpdatePanel>
 <br />
 <asp:Button ID="Button1" runat="server" οnclick="Button1_Click" Text="更新时间" />

而在后置代码中,我们只需要像平常的Asp.Net开发一样,编写Button控件的Click事件处理程序就可以了:

protected void Button1_Click(object sender, EventArgs e) {
     Label1.Text = DateTime.Now.ToLongTimeString();
 }

OK,现在一切都已经就绪了,如果你运行这个页面,并且点击Button,会看到Label的值变为了最新的时间,而且没有因为PostBack所产生的页面闪动,即是人们常说的无刷新更新页面。这可能是实现一个Asp.Net Ajax的最简单范例了。但是它的问题是什么呢?当我们点击Button的时候,在服务端执行了一个完整的Asp.Net 页面生命周期,和你不使用UpdatePanel更新页面没有任何的区别。可以做一个测试,在页面在拖放一个Label,ID为Label2,然后在Page_Load中写入下面代码:

protected void Page_Load(object sender, EventArgs e) {
    if (!IsPostBack) {
        Label2.Text = DateTime.Now.ToLongTimeString();
    } else {
        Label2.Text = DateTime.Now.ToLongTimeString();
    }
}

然后在Page_Load一行设置断点,接下来运行调试,会发现每次你点击Button按钮的时候,都会运行else{...}中的语句,说明每次页面都会执行Page_Load方法。这说明使用这种方式时,服务器端的开销是比较大的。这里还可以发现一个有趣的现象,尽管服务器执行了为Label2.Text赋值的语句,但是页面上Label2却并没有更新。如果想要更新它,那么需要将它也放置到UpdatePanel中,这里我们可以在页面上重新拖放一个UpdatePanel,然后把Label2放置进去。然后我们再点击Button,会发现Label1和Label2都进行了更新。这里又引出了一个有趣的问题:回想一下前面,我们只为第一个UpdatePanel设置了Triggers节点,而并没有为后来新添的UpdatePanel设置Triggers节点,但是对一个UpdatePanel的更新也会影响到另一个。有的时候这种情况是我们所需要的,但更多时候不是,我们可能希望对于Label2的更新由其他控件的其他事件触发。此时,可以将第二个UpdatePanel的UpdateMode属性设为“Conditional”,就避免了受到其他UpdatePanel提交的影响,这个值默认为“Always”。

下面是此时Aspx页面的代码:

<!-- 上面相同 -->
<hr /><br />
<asp:UpdatePanel ID="UpdatePanel2" runat="server" UpdateMode="Conditional">
 <ContentTemplate>
     <asp:Label ID="Label2" runat="server" Text="[未设置]"></asp:Label>
 </ContentTemplate>
</asp:UpdatePanel>

以上这些就是一种最常见的Asp.Net Ajax开发模式了,我们看到它如何实现,也看到了它的缺陷:每次客户端的操作,都会在服务端执行一次完整的页面生命周期,加重了服务器的负担,同时客户端和服务端的通信过程中也会传递完整的http协议内容,增大了网络流量。我们也应该看到它的优点:实现起来非常的简单,操作上基本等同于通常的Asp.Net开发,所使用的控件也为Asp.Net服务器控件(Server Control,这里相对于HTML控件而言)

Asp.Net Ajax - Web Service模式

还有一种方式就是Web Service模式了,客户端不再提交页面,而只是发送Web Service请求,并对收到应答进行处理。由于这里采用了异步方式,所以客户端在发送WebService请求之后无需等待。采用这种方式服务端不会执行生命周期,往返的数据量也减到了最小。但缺点就是需要手动编写一些代码。我们来一步步看下如何完成,因为WCF是下一代Windows平台通信的基础,集成了Web Service和Remoting这两大技术,所以我们采用WCF来创建服务。

首先选择“添加新项”,然后选择“启用了AJAX的WCF服务”,输入名称SimpleService,这样会在站点中添加一个SimpleService.svc文件,在App_Code中创建一个SimpleService.cs,还会在Web.Config中添加相关的配置。我们只需要改动一下App_Code中的SimpleService.cs下的代码:

public class SimpleService
{
    [OperationContract]
    public string GetCurrentDate(string clientValue) {
        string rtn = "Server Time :" + DateTime.Now.ToLongTimeString() + "<br />";
        rtn += "Client Value(round trip): " + clientValue;
        return rtn;
    }
}

SimpleService还用一些特性修饰了,我将它取消掉了以节省空间。方法接受一个字符串clientValue,然后获取服务器时间,最后返回clientValue。这段代码看上去没有什么特别之处,但是注意到我在Client Value旁加了一个括号,写着“round trip”,对于Ajax程序来说,这个值由客户端发送,最后再返还给客户端,进行了一趟由客户端到服务端,再到客户端的周游。

为了要让javascript可以调用这个Web服务,我们需要在aspx页面中对它进行注册,拖放也一个ScriptManager到页面上,然后向下面这样进行设置:

<asp:ScriptManager ID="ScriptManager1" runat="server">
    <Services>
        <asp:ServiceReference Path="~/SimpleService.svc" />
    </Services>
</asp:ScriptManager>

接下来我们新建一个Pattern2.aspx页面,在上面拖放三个HTML标记。一个span,一个input(Button),一个input(Text)。注意,是客户端HTML标记,不含有runat="server"的,从这里已经可以看到一个很大的不同,我们使用的是客户端HTML控件。接着在input(Button)上双击,会自动生成Javascript脚本,此时aspx页面的主要代码如下:

<input id="txtSample" type="text" style="width:120px" /><br />         
<span id="spnTime">[未设置]</span><br />
<br />
<input id="Button1" type="button" value="更新时间" οnclick="return Button1_onclick()" />

最关键是接下来要编写的javascript代码,我先将它贴出来,然后再进行解释:

<script language="javascript" type="text/javascript">
function Button1_onclick() {
    var context = "Callback Values";                // 传给回调函数
    var clientValue = $get("txtSample").value;      // 获得TextBox的值
    SimpleService.GetCurrentDate(clientValue, OnComplete, OnFailed, context);  
    return true;
}

function OnComplete(args, context){
    alert(context);
    var span = $get("spnTime");
    span.innerHTML = args;
}

function OnFailed(args){
    alert("更新日期失败!");
}
</script>

首先看这个Button1_onclick()方法,我们先声明了一个context,这个content很类似于在C#的委托变量上调用BeginInvoke()方法时的最后一个参数,这个值用于传递给回调函数,以方便进行一些处理。接着我们获取了input(Text)中输入的值,保存在了clientValue中。然后调用了Web服务,其中第一个参数就是上面定义的GetCurrentDate()时的参数,我们传入了clientValue,第二个参数是OnComplete是成功时的回调函数,第三个是OnFailed是失败时的回调函数,最后一个参数我们传递了context,可以将它交由回调函数处理。因为是异步操作,所以没有在这里获取GetCurrentDate()方法返回值,而是通过回调函数OnComplete的参数对返回值进行了传递。

接下来看OnComplete()函数,其实我们最需要搞清楚的就是它的两个参数:第一个args即为Web服务方法GetCurrentDate()的返回值;而第二个参数,即为调用GetCurrentDate()时传递的最后一个参数。在方法内部,我们使用alert()显示了context的值,随后将Web服务的返回值显示在了span中。OnFailed()仅仅是提示用户更新失败。

接下来在页面上点击Button,应该可以看到下面的效果:

我们再次在Page_Load的位置设置断点,然后启动调试,会发现当我们使用这种方式时,点击Button服务端并没有再次执行页面生命周期,而参与客户端/服务端往返的数据也是最少量的(仅往返必需数据),因此,虽然采用这种方式我们需要编写一定量的javascript代码,但是却能够显著地提高站点的性能。

总结

这篇文章简单的讲述了使用Asp.Net Ajax进行开发时常见的两种方式,使用UpdatePanel + 服务器控件;或者是使用 Web Service + HTML标记 + Javascript,并且这两种方式的实现方式和效果做了简要的说明。

感谢阅读,希望这篇文章能给你带来帮助!

转载于:https://www.cnblogs.com/JimmyZhang/archive/2008/11/05/1327709.html

Asp.Net Ajax的两种基本开发模式相关推荐

  1. QtCreator与catkin命令两种方式开发ROS程序(图示加代码)

    QtCreator与catkin命令两种方式开发ROS程序(图示加代码) 一.Qt Creator安装及开发ROS 1.安装Qt Creator 2.使用Qt Creator开发ROS 1.创建工作空 ...

  2. 嵌入式系统实验——【玄武F103开发板】顺序点亮4小灯和4小灯全亮两种点亮模式、并使用KEY1控制切换点亮模式

    一.实验目的 顺序点亮4小灯和4小灯全亮两种点亮模式.并可以使用KEY1控制切换点亮模式 二.实验思路: (一)示例程序分析 #include "stm32f10x.h" type ...

  3. 100A有源电力滤波器(APF)MATLAB仿真,两种谐波补偿模式:全阶补偿和选阶补偿

    100A有源电力滤波器(APF)MATLAB仿真,两种谐波补偿模式:全阶补偿和选阶补偿,matlab版本V2011,基于LCL滤波器的I型三电平拓扑仿真模型,三相四线制,软件锁相环,C语言编程提取谐波 ...

  4. 深入php-fpm的两种进程管理模式详解

    php-fpm的两种进程管理模式 php-fpm的进程数也是可以根据设置分为动态和静态的. 一种是直接开启指定数量的php-fpm进程,不再增加或者减少: 另一种则是开始的时候开启一定数量的php-f ...

  5. 认识LTE(七):LTE中的两种无反馈模式:发射分集(TM2)和开环空分复用(TM3)

    认识LTE(七):LTE中的两种无反馈模式:发射分集(TM2)和开环空分复用(TM3) 文章目录 认识LTE(七):LTE中的两种无反馈模式:发射分集(TM2)和开环空分复用(TM3) 零.代码地址 ...

  6. 上汽大通MIFA 7通过申报,提供可换电和充电两种补能模式

    车控快讯(文/每日一CHEK)上汽大通MIFA 7通过申报,定位为纯电中型MPV,提供6/7座布局和可换电和充电两种补能模式.新车的外观设计简洁明了,采用环装灯带和泪眼式灯组构成的前脸和"7 ...

  7. 【转】【Asp.Net】Asp.net发送邮件的两种方法小结

    这几天看了一下Asp.net发送邮件方面的东西,记得之前的IIS6上有SMTP服务器,可以直接利用这个进行邮件发送,现在的开发环境是Windows 7,找了半天没有找到,到网络上查了才知道原来wind ...

  8. Asp.net发送邮件的两种方法小结

    这几天看了一下Asp.net发送邮件方面的东西,记得之前的IIS6上有SMTP服务器,可以直接利用这个进行邮件发送,现在的开发环境是Windows 7,找了半天没有找到,到网络上查了才知道原来wind ...

  9. ASP.NET AJAX,WCF,ADO.NET Entity 开发实例

    开发环境:Windows server 2008 Enterprise,Microsoft Visual Studio 2008 SP1,.NET Framework 3.5 SP1,Microsof ...

最新文章

  1. 【数据结构作业心得】纸面6 - Matlab LU分解
  2. oracle链接字符串java,java连Oracle连接字符串写法
  3. WebView 实现JS效果和a标签的点击事件
  4. 012_Java操作FastDFS
  5. Styled Label
  6. 信息学奥赛一本通 1074:津津的储蓄计划 | 1835:【04NOIP提高组】津津的储蓄计划 | OpenJudge NOI 1.5 22
  7. linux基本命令示例_Linux正常运行时间命令示例
  8. 【图像处理】hough变换_检测直线
  9. java itext 页边距_iText的用法
  10. ansi编码转换器安卓版_ANSI Converter-ANSI码转换器
  11. 京东/拼多多淘客小程序跳入路径
  12. 使用python中的zellers一致性计算星期几
  13. STM32CUBE——使用DWT提供毫秒延迟
  14. Pytest setup teardown
  15. kanzi 粒子插件
  16. 解读电力调度、电力市场、技术创新,国网南网新型电力系统行动方案
  17. 火车头 采集 java 生成正文_火车头采集器使用教程–采集内容发布规则设置
  18. OpenHarmony编译
  19. R语言解读自回归模型
  20. 又拍网架构 -- 前端PHP后台Python +消息中间件 RabbitMQ + 分库步骤

热门文章

  1. SharePoint 2010 同步用户Services 一直Starting 终极解决方案
  2. extjs 表单验证实例
  3. android webView加载网络视频
  4. Android中Application类用法
  5. 接口继承中一个常见问题的思考
  6. Python OpenCV实现鼠标画框
  7. c++文件中jni库找不到报红
  8. eclipse开发cocos2dx 3.2环境搭建之三: ccp-tests项目编译 (this project is not a CDT project)
  9. 团队作业-Beta冲刺(周三)
  10. [数论]Gcd/ExGcd欧几里得学习笔记