• 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" onclick="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="120px" /><br />          
    <span id="spnTime">[未设置]</span><br />
    <br />
    <input id="Button1" type="button" value="更新时间" onclick="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,并且这两种方式的实现方式和效果做了简要的说明。

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

    转自:http://www.tracefact.net/Article/Ajax-Pattern.aspx

  • 相关阅读:
    队列的链式存储结构实现
    堆栈的链式存储实现
    使用C#改变windows系统本地时间
    oracle 多数值录入校验(分隔符“/”)
    oracle中in和exists的区别
    redis安装 windows版(图形化安装)
    Oracle 返回结果集
    饿了么4年 + 阿里2年:研发路上的一些总结与思考
    Oracle 获取各类时间
    Oracle表中已有数据,修改字段长度
  • 原文地址:https://www.cnblogs.com/suncms/p/2497196.html
Copyright © 2020-2023  润新知