客户端回发/回调揭密

本文节选自《庖丁解牛:纵向切入ASP.NET 3.5控件和组件开发技术》一书

对于服务端控件元素,比如ASP.NET的Button标准服务端控件在提交时可以自动把请求发送到服务端处理,这样的控件我们不用自己处理它们的事件回发;但对于呈现不引起回发的HTML元素,如“文本框”(TextBox)或“链接按钮”(LinkButton),而希望由控件启动回发,则可以在ASP.NET中通过依靠客户端脚本的事件结构进行编程来实现这一功能。
    完整地处理一个事件则还需要回发和捕捉。捕捉是IPostBackEventHandler接口的事情,上一节讲得比较清楚了,这一节主要讲回发(客户端回发请求到服务端)。
下面就以一些常用的HTML标记展开分析客户端回发机制,以及各种HTML标记的回发形式。
5.2.2.1  设置HTML Button标记的类型为submit
如上节的PostBackEventControl控件例子就是采用设置HTML Button标记的类型为submit的方式从客户端提交回发的。回发代码如下:
output.Write("<INPUT TYPE=submit name=" + this.UniqueID + " Value='单击我' />");
INPUT是标准的HTML标记控件,它默认情况下没有runat="server",并且这些控件默认情况下只能处理一些客户端方法。INPUT的TYPE属性表示该标记的控件类型,如:type=button表示按钮;type=submit表示可提交表单功能的按钮;type=text表示文本框控件;type=file表示上传文件控件等。这里主要说明的是当type=submit类型的控件表示提交按钮时,它显示的样式与type=button的效果一样,不同的是单击它后可以提交表单到服务器,且不需要另外的代码,ASP.NET默认情况下是提交表单到当前页面。type=submit提交功能是从IE 3.0版开始支持的,只要浏览器版本不小于此版本都可使用该功能。
5.2.2.2  使用方法GetPostBackEventReference 得到回发脚本
1.为HTML客户端控件增加回发功能
一般页面中的按钮并不都是type=submit类型的,大部分是type=button类型的按钮,把上面5.2.2.1节的代码段中的type=submit修改成type=button,修改后的代码如下:
output.Write("<INPUT TYPE=button name=" + this.UniqueID + " Value='[使用提交按钮]' />");
由于此代码段中的按钮的type属性由sumbit改成了一般按钮类型button,则此按钮输出后将不再具有回发到服务端的功能。为了使一般按钮也具有回发的功能,ASP.NET提供了Page.ClientScript.GetPostBackEventReference方法。ClientScript类型为ClientScriptManager,该类主要功能是在Web应用程序中定义用于管理客户端脚本的方法。GetPostBackEvent Reference方法体结构如下:
GetCallbackEventReference(String, String, String, String, String, Boolean) 
此方法功能是获取一个对客户端函数的引用;调用该方法时,将启动一个对服务器事件的客户端回调。此重载方法的客户端函数包含指定的目标、参数、客户端脚本、上下文、错误处理程序和布尔值。
在期望不执行回发而从客户端运行服务器代码的情况下,可以使用ClientScriptManager类来调用客户端回调。这称为对服务器执行带外回调。在客户端回调中,客户端脚本函数向ASP.NET网页发送异步请求。网页修改其正常生命周期来处理回调。使用GetCallbackEvent Reference方法获取一个对客户端函数的引用,当调用该函数时,它将启动一个对服务器端事件的客户端回调。
使用GetCallbackEventReference方法对上面代码增加回调客户端功能,修正后的代码如下:
output.Write("<INPUT type=button name=/"{0}/" value='[使用Page.ClientScript对象方法]' οnclick=/"{1}/">", this.UniqueID, Page.ClientScript.GetPostBackEvent Reference(this, ""));
Page.ClientScript.GetPostBackEventReference方法的第一个参数传递当前控件引用,在实际应用中可以传递任意控件引用,包括子控件;第二个参数为可选的命令参数,这里设置为null,一般同时处理多个按钮时可以设置该参数为不同的命令名称。
另外,Page.ClientScript对象还有个非常重要的方法GetCallbackEventReference。使用GetCallbackEventReference方法获取一个对客户端函数的引用,当调用该函数时,它将启动一个对服务器端事件的客户端回调,可以支持设置客户端回调方法名称等,在这里仅简单提一下,在后面还有专门章节介绍ASP.NET控件开发对客户端的支持。
转入正题,在代码中增加按钮的onclick单击事件,当单击按钮时会调用GetPostBackEvent Reference方法返回的一串客户端脚本,并且在页面中生成一个客户端方法和两个type=hidden的隐藏域控件。下面是以上代码呈现到客户端的HTML代码:
<INPUT type=button name="PostBackFromClientControl1"value='[使用Page. ClientScript对象方法]'οnclick="__doPostBack('PostBackFromClientControl1','')">
<div>
    <input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
    <input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
</div>
<script type="text/javascript">
    //<![CDATA[
    var theForm = document.forms['form1'];
    if (!theForm) {
        theForm = document.form1;
    }
    function __doPostBack(eventTarget, eventArgument) {
        if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
            theForm.__EVENTTARGET.value = eventTarget;
            theForm.__EVENTARGUMENT.value = eventArgument;
            theForm.submit();
        }
    }
    //]]>
</script>
从上面最终输出的HTML源代码可以看到,Button控件的单击事件会执行一个名为_doPostBack的方法,并且此方法也是自动生成在页面中的。在_doPostBack方法中把事件目标对象eventTarget(调用GetPostBackEventReference方法时传递的第一个参数,为当前控件)赋值给当前Form对象,把事件参数对象eventArgument(调用GetPostBackEventReference方法时传递的第二个参数),最后调用Form对象的提交方法,提交窗体,到这里就实现了我们想要的回发功能。
还要注意到以下两句自动生成的代码:
<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
这是两个隐藏域类型控件,主要用来存储事件目标对象和事件参数对象的值。还有,在以上的script标记之间,有个嵌套的//<![CDATA[  //]]> 子句,该句与纯控件开发技术无关。该句的功能是通知HTML读取器下面这段不是HTML的内容,需要按附加的转义字符分开保存,以防代码解析出错。
2.为服务端控件生成回发脚本
Page.ClientScript.GetPostBackEventReference方法还可以为服务端控件生成自己的回发脚本,可以从客户端回发。
ASP.NET标准的Button服务端控件最终生成的HTML标记无非也是生成一个type=submit类型的控件。对于服务端控件也可以设置客户端回发功能。比如在使用Button控件时把UseSubmitBehavior属性设置为false,则禁用按钮的自动提交功能,就可以使用GetPostBackEventReference方法返回Button控件的客户端回发事件脚本,代码如下所示:
string strPostBackCode =
this.Page.ClientScript.GetPostBackEventReference(button1,”edit”);
然后把Button的客户事件与生成的回发事件脚本进行关联:
this.button1.Attributes[“onclick”] = strPostBackCode;
其他服务端控件也是这样设置的。
5.2.2.3  使用方法GetPostBackClientHyperlink得到回发脚本
这种方式的原理与GetPostBackEventReference类似。该方法的功能是获取一个脚本引用,与前者有一点区别是在其开头附加一个javascript: 前缀,该前缀属于JavaScript基本语法,常用来在非脚本语言(如HTML)源代码中告诉浏览器该前缀后面的格式串作为JavaScript脚本语言来解析,如:javascript:alert(‘hello’)即表示弹出一个“hello”对话框。该引用可在客户端事件中回发到指定控件的服务器,回发时使用指定的事件参数和一个布尔值指示是否为事件验证注册该回发。方法体结构如下:
GetPostBackClientHyperlink(Control, String, Boolean) 
跟GetPostBackEventReference相同,第一个参数为事件目标对象;第二个参数为可选参数;第三个参数表示是否为验证注册回发事件。
下面看一个应用示例,代码如下:
string href  = Page.ClientScript.GetPostBackClientHyperlink(this, "");
output.AddAttribute(HtmlTextWriterAttribute.Href, href);
output.RenderBeginTag(HtmlTextWriterTag.A);
output.Write("[使用Page.ClientScript对象的GetPostBackClientHyperlink方法]");
output.RenderEndTag();
与前面不同,这里是输出一个HTML的<a>标签。相信读者已经猜到GetPostBackClientHyperlink的应用场景了(通过方法名***Hyperlink就能够看得出它是专为哪个控件使用的功能)。直接看一下最终生成的客户端的HTML源代码:
<a href="javascript:__doPostBack('PostBackFromClientControl1','')">[使用Page.ClientScript对象的GetPostBackClientHyperlink方法]</a>
<div>
    <input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
    <input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
</div>
<script type="text/javascript">
    //<![CDATA[
    var theForm = document.forms['form1'];
    if (!theForm) {
        theForm = document.form1;
    }
    function __doPostBack(eventTarget, eventArgument) {
        if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
            theForm.__EVENTTARGET.value = eventTarget;
            theForm.__EVENTARGUMENT.value = eventArgument;
            theForm.submit();
        }
    }
    //]]>
</script>
从上面代码可以看到,除了这句:
href="javascript:__doPostBack('PostBackFromClientControl1','')"
链接触发方式与前面Button控件的onclick触发方式有些不同外,其他的代码完全正确一样。
另外,ASP.NET会自动处理可重用部分代码,比如当页面中有多个可提交元素时,处理页面提交的公共方法_doPostBack在当前页面中总是生成一个,不会生成冗余。
关于GetPostBackClientHyperlink方法的使用就讲这么多。本节主要讲几种常用HTML标签的调用客户端回发的方式以及客户端回发的原理。注意,使用GetPostBackEventReference方法和GetPostBackClientHyperlink方法定义客户端回发事件。这些方法启用客户端脚本函数,在调用这些函数时,它们将促使服务器向该页回发。客户端回发与客户端回调的区别在于网页处理客户端回发事件要用完一个正常的生命周期,而GetCallbackEventReference是异步请求,在客户端回调中,客户端脚本函数向ASP.NET网页发送异步请求,网页修改其正常生命周期来处理回调。两者调用是有些区别的。每个功能点在随书光盘中都有完整的示例代码。

ASP.NET 3.5控件和组件开发技术之客户端回发/回调揭密相关推荐

  1. 英文版资料[庖丁解牛—纵向切入Asp.net 3.5控件和组件开发技术]

    英文版资料[庖丁解牛-纵向切入Asp.net 3.5控件和组件开发技术] . Carving Up an Ox * Book Name <Carving Up an Ox: In-depth A ...

  2. 庖丁解牛:纵向切入ASP.NET 3.5控件和组件开发技术

    今天看到一本电子书,郑健写的,关于控件和组件开发技术的,总体还不错,推荐给大家看看. 本书详细信息 前言与目录 庖丁解牛 前言 庖丁解牛 目录 序 庖丁解牛 序一 庖丁解牛 序二 第2章 服务器控件开 ...

  3. ★★★【庖丁解牛:纵向切入Asp.net 3.5控件和组件开发技术系列—(1)读者序】★★★...

    本书主要内容 大部分开发人员在学习Asp.net的过程中都有这样的体会,使用Asp.net开发很多年,但仍然感觉对Asp.net技术的了解比较少,对知识点的了解比较模糊:以及,在工作过程中经常接到克刻 ...

  4. 《纵向切入ASP.NET 3.5控件和组件开发技术》笔记:高效率事件集合对象

    在之前讲的几个例子中,使用的是最普通的定义事件方法,比如KingTextBox中事件是这样定义的: /// <summary> /// 获得本书更多内容,请看: /// http://bl ...

  5. 庖丁解牛ASP.NET3.5控件和组件开发技术-(1)服务器控件概述

    服务器控件概述 1.服务器控件的类型以及ASP.NET控件开发的系统基类 Control,WebControl,CompositeControl,DataBoundControl,Hierarchic ...

  6. 构建安全的 ASP.NET 网页和控件

    本页内容 本模块内容 目标 适用范围 如何使用本模块 威胁和对策 设计注意事项 输入验证 跨站点脚本 身份验证 授权 模拟 敏感数据 会话管理 参数处理 异常管理 审核和日志记录 小结 其他资源 本模 ...

  7. ASP.NET Atlas简单控件介绍——Sys.Component基类与Sys.UI.Control基类

    作者:Dflying Chen (http://dflying.cnblogs.com/) 本系列有三篇文章: ASP.NET Atlas简单控件介绍--Sys.Component基类与Sys.UI. ...

  8. asp.net的常用控件

    ASP.NET常用第三方控件列表 ASP.NET 漂亮的免费甘特图控件 基于flash与javascript的客户端文件上传组件 在线Word/excel/wps编辑辅助控件 一个三维动态滑块效果的功 ...

  9. ASP.NET2.0 分页控件 PagerPro.dll (1.1.0 最新)

    快来瞧,快来看了啊,新出炉的ASP.NET分页控件,热乎啦! 最新的ASP.NET2.0分页控件,经过对样式的处理,现有None和Standard两种样式,可以自定义是否显示Page Count 和 ...

  10. DateChooser控件发布ASP.NET 2.0新版(我的ASP.NET 2.0控件开发书的第二个阶段项目)[请大家一定注意版本的更新,下载最新版]...

    已更新实用版:DateChooser ASP.NET 2.0版 之实用版 请大家一定注意版本的更新,下载最新版 DateChooser的ASP.NET 1.x版在二年前就发布了,二年以来,ASP.NE ...

最新文章

  1. 编程面试过程中最常见的10大算法
  2. write/read/send/receive函数比较
  3. DCMTK:将STL文件封装为DICOM文件
  4. 如何在 IntelliJ IDEA 中整合 Maven、Tomcat 部署 Web 应用
  5. python3(十二)打开和关闭文件
  6. es6 作为属性名的 Symbol
  7. PB调用C# Windows窗体
  8. 数据链路的基本概念和功能概述
  9. TYUT程序设计比赛2017回顾
  10. 语音识别相关工具和资料分享
  11. 咚咚咚————【Matlab】单片机读取摄像头回传的RGB数组绘制图片
  12. 【租房必看】有了这份租房指南,再也不怕被坑了!(建议收藏)
  13. Apple Pay接入详细教程
  14. 计算机模拟做报童模型,用基于计算机随机模拟的下降法求解报童问题
  15. 基本遗传算法(GA)详解
  16. ps 毛发 边缘,抠图技巧,抠图后头发边缘的颜色怎处理
  17. 对硬盘进行分区时,GPT和MBR有什么区别
  18. Civil3D 2018-03 曲面创建
  19. 状态码(304 详解)
  20. 纹理压缩(二) ETC格式

热门文章

  1. R学习-小白笔记08
  2. oracle 数据库汉字乱码
  3. 规范信息系统工程建设市场 促进信息化健康发展
  4. angular动态绑定样式以及改变UI框架样式的方法
  5. Injection with CDI (Part I)
  6. win7下cmd常用命令
  7. iphone:使用NSFileManager取得目录下所有文件(遍历所有文件)
  8. 各种推荐算法的 benchmark
  9. 文本分类和意图识别调研思考
  10. 苏神吐槽 | 开局一段扯,数据全靠编?真被一篇“神论文”气到了