《征服ASP.NET2.0AJAX》一书的读后总结(第十五章Microsoft ASP.NET Ajax核心组件章)

来源:互联网 发布:电视直播软件 央视 编辑:程序博客网 时间:2024/04/29 19:58

 
<!--[if !supportLists]-->第一章<!--[endif]-->Microsoft ASP.NET Ajax核心组件
<!--[if !supportLists]-->1.         <!--[endif]-->ScriptManager脚本控制器

ScriptManager控件包括在ASP.NET 2.0 AJAX Extensions中,它用来处理页面上的所有组件以及页面局部更新,生成相关的客户端代理脚本以便能够在JavaScript中访问Web Service,所有需要支持ASP.NET AJAX的ASP.NET页面上有且只能有一个ScriptManager控件。在ScriptManager控件中我们可以指定需要的脚本库,或者指定通过JS来调用的Web Service,还可以指定页面错误处理等。

使用<asp:ScriptManager/>来定义一个ScriptManager,简单的ScriptManager定义形式:

<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true" AllowCustomErrorsRedirect="false"  AsyncPostBackErrorMessage=""    AsyncPostBackTimeout="90"  OnAsyncPostBackError="" ScriptPath="" ScriptMode="Auto" OnResolveScriptReference="" >

            <AuthenticationService  Path=""/>

            <ProfileService  Path="" LoadProperties=""/>

            <Scripts>

                <asp:ScriptReference  Path=""/>

            </Scripts>

            <Services>

                <asp:ServiceReference Path="" />

            </Services>

        </asp:ScriptManager>

属性/方法
 描述
 
EnablePartialRendering
 标识此页内是否允许局部刷新
 
AllowCustomErrorsRedirect
 但Ajax错误发生后,是否导航到Web.config中的自定义错误配置区<customErrors>,如果为false,则可以使用下面两个属性实现错误提示;
 
AsyncPostBackErrorMessage
 异步回传发生错误时的自定义提示错误信息。
 
OnAsyncPostBackError
 异步调用发生时的事件。异步回传发生异常时的服务端处理函数,在这里可以捕获一场信息并作相应的处理。
 
AsyncPostBackTimeout
 异步调用的有效时间,默认值为90,单位为秒
 
ScriptMode
 指定ScriptManager发送到客户端的脚本的模式,有四种模式:Auto,Inherit,Debug,Release,默认值为Auto,后面会仔细说到。
 
ScriptPath
 设置所有的脚本块的根目录,作为全局属性,包括自定义的脚本块或者引用第三方的脚本块。如果在Scripts中的<asp:ScriptReference/>标签中设置了Path属性,它将覆盖该属性。
 
OnResolveScriptReference
 指定ResolveScriptReference事件的服务器端处理函数,在该函数中可以修改某一条脚本的相关信息如路径、版本等。
 
AuthenticationService 
 用来提供验证服务的路径
 
ProfileService 
 个性化服务的路径
 
Scripts
 对脚本的调用,可以实现多个脚本文件
 
Services
 对服务的调用,可以实现多个服务
 
 
 
 

客户端脚本模式

在前面我们提到了ScriptMode属性指定ScriptManager发送到客户端的脚本的模式,它有四种模式:Auto,Inherit,Debug,Release,默认值为Auto。

1.Auto:它会根据Web站点的Web.config配置文件来决定使用哪一种模式,只有当配置文件中retail属性设置为false:

<!--[if !vml]--><!--[endif]--><system.web>
<!--[if !vml]--><!--[endif]-->  <deployment retail="false" />
<!--[if !vml]--><!--[endif]--></system.web>

或者页面中的Debug指令设为true的时候会使用Debug版本,其他的情况都会使用Release版本。

<!--[if !vml]--><!--[endif]--><%@ Page Language="C#" Debug="true"AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

2.Inherit:应该是通过程序设置ScriptMode的时候,等同于Auto?(不太了解)

3.Debug:客户端脚本使用Debug版本,除非retail(零售)属性设为true。

4.Release:客户端脚本使用Release版本,除非retail属性设为false。

 

调用脚本

(1)

Asp.net 2.0 注册脚本的方式

<head runat="server">

    <title>统计工具</title>

    <script type="text/jscript" src="../../js/OperateCookie.js"></script> 

</head>

在Asp.net 2.0 Ajax中的脚本注册方式

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

            <Scripts>

                <asp:ScriptReference  Path="../../js/OperateCookie.js "/>

            </Scripts>

        </asp:ScriptManager>

上述两种定义方式运行后生成的客户端脚本完全一致;

(2)

Asp.net 2.0 Ajax的<Scripts>子元素还可以调用Ajax类库中已存在的Javascript脚本文件

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

            <Scripts>

<asp:ScriptReference   Assembly="Microsoft.Web.Preview" Name="PreviewScript.js"/>

<%--Assembly:为脚本库类所在的程序集(Microsoft.Web.Preview为CTP增值组件),Name引用脚本文件名 --%>

            </Scripts>

 </asp:ScriptManager>

关于Scripts属性,最主要的属性有Path指定脚本的路径,ScriptMode指定客户端脚本的模式,它会覆盖ScriptManager中的ScriptMode属性,还有一个属性是IgnoreScriptPath,指定是否忽略掉ScriptManager中的ScriptPath属性。

调用web Service步骤:

<!--[if !supportLists]-->(1)       <!--[endif]-->首先创建web Service,

<!--[if !supportLists]-->(2)       <!--[endif]-->然后给给它添加[System.Web.Script.Services.ScriptService]属性,以便ScriptManager识别这个服务

/// <summary>

/// WebService1 的摘要说明

/// </summary>

[WebService(Namespace = "http://tempuri.org/")]

[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]

[System.Web.Script.Services.ScriptService]

public class WebService1 : System.Web.Services.WebService {

    public WebService1 () {

        //如果使用设计的组件,请取消注释以下行

        //InitializeComponent();

    }

    [WebMethod]

    public string HelloWorld() {

        return "Hello World";

    }

}

<!--[if !supportLists]-->(3)       <!--[endif]-->在ScriptManager控件内注册服务

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

            <Services>

                <asp:ServiceReference Path="WebService1.asmx" />

            </Services>

     </asp:ScriptManager>

<!--[if !supportLists]-->(4)       <!--[endif]-->在页面的head元素内添加JavaScript对服务的引用

<head runat="server">

    <title>无标题页</title>

    <script type="text/javascript">

    //引用web服务

    function RefService1()

    {

       //返回值与js处理事件挂钩

       WebService1.HelloWorld(GetResult);

    }

    function GetResult(result)

    {

      //提示返回数据

       alert(result);

    }

    </script>

</head>

<body>

    <form id="form1" runat="server">

    <div>

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

            <Services>

                <asp:ServiceReference Path="WebService1.asmx" />

            </Services>

        </asp:ScriptManager>

    <input type="button" value="不带参数的服务" onclick="RefService1()" />

    </div>

    </form>

</body>

</html>

通过<asp:ServiceReference>标签可以在Services中注册一个WebService,在运行时ScriptManager将为每一个ServiceReference对象生成一个客户端代理,<asp:ServiceReference>标签一个很重要的属性是Path,用来指定WebService的路径

因为ScriptManager为服务器端控件所以也可以动态加载服务

//创建一个服务引用对象

        ServiceReference service = new ServiceReference("WebService2.asmx");

        //将服务对象添加到脚本控制器中

        ScriptManager1.Services.Add(service);

 

错误处理

在页面回传时如果发生了异常AsyncPostBackError事件将被触发,错误信息的处理依赖于AllowCustomErrors属性、AsyncPostBackErrorMessage属性和Web.config中的<customErrors>配置区。下面看一个简单的错误处理例子,在AsyncPostBackError事件中捕获到异常信息并设置AsyncPostBackErrorMessage属性。

注:错误是针对局部刷新而言的,所以是处理UpdatePanel控件的错误;

 

2、ScriptManagerProxy控件

在ASP.NET AJAX中,由于一个ASPX页面上只能有一个ScriptManager控件,所以在有母版页的情况下,如果需要在Master-Page和Content-Page中需要引入不同的脚本时如在母版页引入A脚本可是还要在内容页引入B,如果母版页把A,B都引入的话,对于不需要B脚本的内容页就会影响性能,这就需要在Content-page中使用ScriptManagerProxy,而不是ScriptManager,ScriptManager 和 ScriptManagerProxy 是两个用法非常相似的控件。

 

3、UpdatePanel控件

UpdatePanel可以用来创建丰富的局部更新Web应用程序,它是ASP.NET 2.0 AJAX Extensions中很重要的一个控件,其强大之处在于不用编写任何客户端脚本,只要在一个页面上添加几个UpdatePanel控件和一个ScriptManager控件就可以自动实现局部更新。通过本文来学习一下UpdatePanel工作原理和使用方法。

<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="always"  ChildrenAsTriggers="true" RenderMode="Block">

            <ContentTemplate>

                <% =DateTime.Now.ToString() %>

                <asp:Button ID="Button2" runat="server" Text="ButtonIN" />

            </ContentTemplate>

            <Triggers>

                <asp:AsyncPostBackTrigger ControlID="" EventName="" />

                <asp:PostBackTrigger  ControlID=""    />

            </Triggers>

        </asp:UpdatePanel>

属性
 说明
 
ChildrenAsTriggers
 当UpdateMode属性为Conditional时,UpdatePanel中的子控件的异步回送是否会引发UpdatePanle的更新。
 
RenderMode
 表示UpdatePanel最终呈现的HTML元素。Block(默认)表示<div>,Inline表示<span>
 
UpdateMode
 表示UpdatePanel的更新模式,有两个选项:Always和Conditional。Always是不管有没有Trigger,其他控件(所有UpdatePanel中包括的控件)都将更新该UpdatePanel,Conditional表示只有当前UpdatePanel的Trigger,或ChildrenAsTriggers属性为true时当前UpdatePanel中控件引发的异步回送或者整页回送,或是服务器端调用Update()方法才会引发更新该UpdatePanel。
 
Triggers
 局部跟新触发器,一种是异步回发AsyncPostBackTrigger,可以实现局部刷新,另一种是PostBackTrigger不管是否使用了局部刷新控件,都会引起页面的全部刷新。
 

 

UpdatePanel工作原理

UpdatePanel的工作依赖于ScriptManager服务端控件和客户端PageRequestManager类(Sys.WebForms.PageRequestManager,在后面的客户端类中会专门说到),当ScriptManager中允许页面局部更新时,它会以异步的方式回传给服务器,与传统的整页回传方式不同的是只有包含在UpdatePanel中的页面部分会被更新,在从服务端返回HTML之后,PageRequestManager会通过操作DOM对象来替换需要更新的代码片段。

ContentTemplateContainer属性

如果要使用编程的手法去设置UpdatePanel中的内容,需要创建一个UpdatePanel,并且添加控件到ContentTemplateContainer,而不能直接添加控件到ContentTemplate,如果想直接设置ContentTemplate,则需要编写一个自定义的Template,并去实现位于System.Web.UI命名空间下的接口ITemplate。

<% <!--[if !vml]--><!--[endif]-->@ Page Language="C#" %>
<!--[if !vml]--><!--[endif]--> <!--[if !vml]--><!--[endif]--><script runat="server"> <!--[if !vml]--><!--[endif]-->
<!--[if !vml]--><!--[endif]-->    protected void Page_Load(object sender, EventArgs e)
<!--[if !vml]--><!--[endif]--> <!--[if !vml]--><!--[endif]-->     <!--[if !vml]--><!--[endif]-->{
<!--[if !vml]--><!--[endif]-->        UpdatePanel up1 = new UpdatePanel();
<!--[if !vml]--><!--[endif]-->        up1.ID = "UpdatePanel1";
<!--[if !vml]--><!--[endif]-->        up1.UpdateMode = UpdatePanelUpdateMode.Conditional;
<!--[if !vml]--><!--[endif]-->        Button button1 = new Button();
<!--[if !vml]--><!--[endif]-->        button1.ID = "Button1";
<!--[if !vml]--><!--[endif]-->        button1.Text = "Submit";
<!--[if !vml]--><!--[endif]-->        button1.Click += new EventHandler(Button_Click);
<!--[if !vml]--><!--[endif]-->        Label label1 = new Label();
<!--[if !vml]--><!--[endif]-->        label1.ID = "Label1";
<!--[if !vml]--><!--[endif]-->        label1.Text = "A full page postback occurred.";
<!--[if !vml]--><!--[endif]-->        up1.ContentTemplateContainer.Controls.Add(button1)
<!--[if !vml]--><!--[endif]-->        up1.ContentTemplateContainer.Controls.Add(label1);
<!--[if !vml]--><!--[endif]-->        Page.Form.Controls.Add(up1);
<!--[if !vml]--><!--[endif]-->    }
<!--[if !vml]--><!--[endif]-->    protected void Button_Click(object sender, EventArgs e)
<!--[if !vml]--><!--[endif]--> <!--[if !vml]--><!--[endif]-->     <!--[if !vml]--><!--[endif]-->{
<!--[if !vml]--><!--[endif]-->        ((Label)Page.FindControl("Label1")).Text = "Panel refreshed at " +
<!--[if !vml]--><!--[endif]-->            DateTime.Now.ToString();
<!--[if !vml]--><!--[endif]-->    }
<!--[if !vml]--><!--[endif]--></script>
<!--[if !vml]--><!--[endif]--><html xmlns="http://www.w3.org/1999/xhtml"
<!--[if !vml]--><!--[endif]--><head id="Head1" runat="server">
<!--[if !vml]--><!--[endif]-->    <title>UpdatePanel Added Programmatically Example</title>
<!--[if !vml]--><!--[endif]--></head>
<!--[if !vml]--><!--[endif]--><body>
<!--[if !vml]--><!--[endif]-->    <form id="form1" runat="server">
<!--[if !vml]--><!--[endif]-->        <div>
<!--[if !vml]--><!--[endif]-->            <asp:ScriptManager ID="TheScriptManager"
<!--[if !vml]--><!--[endif]-->                               runat="server" />
<!--[if !vml]--><!--[endif]-->        </div>
<!--[if !vml]--><!--[endif]-->    </form>
<!--[if !vml]--><!--[endif]--></body>
<!--[if !vml]--><!--[endif]--></html>

4、UpdateProgress控件简单介绍

默认情况下,UpdageProgress控件将显示页面上所有的UpdatePanel控件更新的进度信息,在以前版本的UpdateProgress中,我们无法设置UpdateProgress只显示某一个UpdatePanel的更新,最新版本的UpdateProgress控件提供了AssociatedUpdatePanelID属性,可以指定UpdateProgress控件显示哪一个UpdatePanel控件。下面的这个例子中UpdateProgrss控件将只显示它所在的UpdatePanel更新信息。注:UpdateProgress实际是一个DIV,通过代码控制显示还是隐藏,并且放在<ContentTemplate>元素中;

<asp:UpdatePanel ID="UpdatePanel1" runat="server" RenderMode="Inline">

      <ContentTemplate>

           <asp:Label ID="Label1" runat="server" Text="Label" Width="228px"></asp:Label><br />

          <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="更新第一个" />

       <asp:UpdateProgress ID="UpdateProgress1" runat="server" AssociatedUpdatePanelID="UpdatePanel1" DisplayAfter="1000" >

             <ProgressTemplate>

                    第一个正在更新......

              </ProgressTemplate>

        </asp:UpdateProgress>

      </ContentTemplate>

 </asp:UpdatePanel>

属性/方法
 描述
 
AssociatedUpdatePanelID
 表示关联的UpdatePanel
 
DisplayAfter
 多长时间后显示进度条,默认为500单位毫秒
 
ProgressTemplate
 用来设计显示的界面
 

客户端操作UpdateProgress(来自TerryLee AJAX入门

 

在本篇文章中,我们将通过编写JavaScript来使用客户端行为扩展UpdateProgress控件,客户端代码将使用ASP.NET AJAX Library中的PageRequestManager,在UpdateProgress控件中,将添加一个Button,来允许用户取消异步更新,并且使用客户端脚本来显示或者隐藏进度信息。

主要内容

1.通过客户端脚本取消异步更新

2.通过客户端脚本显示或者隐藏进度信息

一.通过客户端脚本取消异步更新

1.创建一个Web页面并切换到设计视图。

2.在工具箱中双击ScriptManager、UpdatePanel、UpdateProgress控件添加到页面中。添加后页面如下:

3.在UpdatePanel控件中添加一个Label控件并设置它的Text属性值为“Panel Rendered”。

4.添加一个Button控件并设置它的Text属性值为“refresh”。

5.在UpdateProgress控件中添加文本text Processing…,并添加一个HtmlButton控件并设置它的Text属性为cancle。

6.双击refresh控件添加Click事件。

7.在Buttond的Click事件处理中添加如下代码,人为的创建一个3秒钟的延迟并显示当前服务器的时间。

protected void Button1_Click(object sender, EventArgs e)
{
    System.Threading.Thread.Sleep(3000);
    Label1.Text = DateTime.Now.ToString();
}

8.添加如下脚本,获取一个当前PageRequestManager类的实例,并创建一个函数调用abortPostBack方法来停止异步更新。

<script language="javascript" type="text/javascript">
<!--
var prm = Sys.WebForms.PageRequestManager.getInstance();
function CancelAsyncPostBack() {

    if (prm.get_isInAsyncPostBack()) {
      prm.abortPostBack();
    }
}
// -->
</script>

9.设置HtmlButton的click特性为CancelAsyncPostBack。

 

10.添加如下的样式块到<head>元素之间。

<style type="text/css">
#UpdatePanel1 {}{
  width:200px; height:100px;
  border: 1px solid gray;
}
#UpdateProgress1 {}{
  width:200px; background-color: #FFC080;
  bottom: 0%; left: 0px; position: absolute;
}
</style>

11.保存并按Ctrl + F5运行。

12.单击refresh按钮,经过短暂的延时之后显示进度信息,完成异步更新之后UpdatePanel中的信息显示为当前的服务器时间。

13.单击refresh按钮并立即单击Cancle按钮结束异步更新,注意到UpdatePanel中的时间信息并没有更新。

二.通过客户端脚本显示或者隐藏进度信息

在下列情况下,UpdateProgress控件将不会自动显示:

    由UpdateProgress控件关联的UpdatePanel之外的控件引发的异步更新。

    UpdateProgress控件没有关联任何UpdatePanel,不在UpdatePanel中的控件引发的异步更新(例如用代码实现的更新)。

下面的例子将展示一个不在UpdateProgress所关联的UpdatePanel中的控件所引发的异步更新时,如何显示UpdateProgress控件。

1.在我们前面所创建的页面中,切换到设计视图。

2.选中UpdateProgress控件,在属性窗口中,设置AssociatedUpdatePanelID属性为UpdatePanel1。

 

3.在UpdatePanel和UpdateProgress控件之外添加一个Button控件。

4.设置Button的Text属性值为Trigger,并设置ID属性为Panel1Trigger。

 

5.选择UpdatePanel控件,在属性窗口中Triggers属性行单击ellipsis (…)。

6.创建一个异步更新触发器,并设置控件ID为Panel1Trigger。

7.双击Trigger按钮添加Click事件。

8.在Buttond的Click事件处理中添加如下代码,人为的创建一个3秒钟的延迟并显示当前服务器的时间,并附加上一条信息表示是由触发器引发的异步更新。

protected void Panel1Trigger_Click(object sender, EventArgs e)
{
    System.Threading.Thread.Sleep(3000);
    Label1.Text = DateTime.Now.ToString() + " - trigger";
}

9.在代码窗口,在已有的<Script>脚本块中添加如下代码:

<script language="javascript" type="text/javascript"><!--
var prm = Sys.WebForms.PageRequestManager.getInstance();
function CancelAsyncPostBack() {
    if (prm.get_isInAsyncPostBack()) {
      prm.abortPostBack();
    }
}
prm.add_initializeRequest(InitializeRequest);
prm.add_endRequest(EndRequest);
var postBackElement;
function InitializeRequest(sender, args) {
    if (prm.get_isInAsyncPostBack()) {
        args.set_cancel(true);
    }
    postBackElement = args.get_postBackElement();
    if (postBackElement.id = 'Panel1Trigger') {
        $get('UpdateProgress1').style.display = 'block';               
    }
}
function EndRequest(sender, args) {
    if (postBackElement.id = 'Panel1Trigger') {
        $get('UpdateProgress1').style.display = 'none';
    }
}
</script>

10.保存并按Ctrl + F5运行。

11.单击Trigger按钮,如下所示:

 

 

5、 Timer控件的简单使用

<asp:Timer ID="Timer1" runat="server" Interval="3000" OnTick="Timer1_Tick">

</asp:Timer>

一个页面只有一个Timer控件实例,每隔Interval时间(毫秒),就执行一次OnTick事件

在服务器端跟新完UpdatePanel的ContentTemplate元素的内容后,自动的进行异步局部刷新;

Timer也可以作为UpdatePanel的触发器,触发事件为Tick;

 

 

Ajax 中的Web服务

<!--[if !supportLists]-->一、  <!--[endif]-->身份验证服务

<!--[if !supportLists]-->二、  <!--[endif]-->个性化配置服务

 

Ajax 的调试和跟踪

由于Ajax的内容进行了封装,如何查找错误的根源,就需要用Ajax的提供的调试类库。Ajax的调试类库位于Sys命令空间下,类库名为Debug主要用来跟踪和调试Ajax运行过程中出现的错误。要启用调试前要引用AJAX脚本类库,但ScriptManager控件会完成对AJAX脚本类库的引用;

方法
 语法
 描述
 
assert
 Sys.Debug.assert(condition,message,diplayCaller)

有问题设置了断点
 //断言

function btnAssert_onclick() {

    txtv = form1.txtname.value;

    Sys.Debug.assert(

        (txtv !== ""),"必须输入姓名");

    alert("你好 " + txtv + ".");

}
 
clearTrace
 Sys.Debug.clearTrace(text)
 //清空跟踪信息

function btnClear_onclick() {

    Sys.Debug.clearTrace()

    alert("跟踪信息清除完毕");

}
 
traceDump
 Sys.Debug.traceDump(object,name)

跟踪对象信息,显示简单的摘要
 //跟踪信息摘要

function btnDump_onclick() {

    Sys.Debug.traceDump(form1.txtname,"TextBox控件");

    alert("你好 " + form1.txtname.value + ".");

}
 
fail
 Sys.Debug.fail(message)

错误调试,添加断点,有问题设置了端点
 //错误

function btnFail_onclick() {

    txtv = form1.txtname.value;

    if (txtv == "") {

        Sys.Debug.fail("必须输入姓名");

    }

    alert("你好 " + txtv + ".");

}
 
trace
 Sys.Debug.trace(text )

写入跟踪信息到Trace输出流
 //跟踪

function btnTrace_onclick() {

    txtv = form1.txtname.value;

    Sys.Debug.trace("您的名字是 " + "/"" + txtv + "/".");

    alert("你好 " + txtv + ".");

}
 

 

调试这些方法时,首先要在IE浏览器为可调试脚本状态

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/zhang_xiao_qing_c_s_/archive/2009/02/10/3874114.aspx

原创粉丝点击