深入理解asp.net中的 __doPostBack函数
前段时间做一个.net网站的时候,用到了模拟前端按钮刷新updatePanel进行局部刷新的时候,遇见了这个问题,当时没顾上记下来,查看网上资料,记下来留着以后查看.
很早以前,当我刚接触asp.NET开发时,我曾有很多很多的疑问(大概是因为我以前一直做jsp开发,也接触过一段时间的asp,脑海中没有这种基于“控件编程”和“事件编程“模型的缘故吧。当然,如果对于一个长期从事桌面程序开发的人,转型做asp.net--webform当然很轻松。)。当我面对这些功能强大的控件,这些属性,这些事件...我常常想知道,她里面到底是如何实现的?例如:Button按钮是如何提交表单的?为啥我在后台可以轻松取到前台页面用户输入的值?如何得到引起页面PostBack的控件?通过阅读Page类的源码(通过阅读源码以及对面向对象思想逐渐的理解,我后来慢慢体会到,其实整个.NET框架,就是按照面向对象的思想去设计的。所以我常用Reflector工具去查看源码,探寻究竟),误打误撞,无意中看到了__EVENTTARGET和__EVENTARGUMENT这两个常量的定义,并通过调试分析页面,知道了通过Request.Form[“__EVENTTARGET”]可以获取到触发页面PostBack的事件源(控件的ID)。对于一般的控件,这样就可以了,唯有Button和ImageButton触发的PostBack无法通过这种方式获取到它们的ID,起初还以为是它们实现的接口的不同而产生PostBack方式的不同。刚刚在AspAlliance.看到一篇关于__doPostBack的文章(原文:《Understanding the JavaScript __doPostBack Function》),才真正明白了页面PostBack的内在机制,疑团也终于解开了。下面来简单看一下页面PostBack的原理,和Button,ImageButton PostBack的特殊性。
__doPostBack是一个纯粹并且是非常简单的JavaScript函数,大部分的页面PostBack都是由它触发的。注意,这里是“大部分”,因为只有两个Web Server Control 会自己触发页面的PostBack,其它的所以控件都是通过__doPostBack函数触发页面的PostBack,那先来看一下这个函数的定义吧:
<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
function __doPostBack(eventTarget, eventArgument) {
if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
theForm.__EVENTTARGET.value = eventTarget;
theForm.__EVENTARGUMENT.value = eventArgument;
theForm.submit();
}
}rm.submit();
通过上面的代码可以看到,__doPostBack带有两个参数,eventTarget是标识将要引发页面PostBack的控件ID,eventArgument参数提供了在引发页面PostBack事件时所带的额外参数。当然这个函数被函数时,这两个参数的值将赋值给页面的两个隐含变量__EVENTTARGET和__EVENTARGUMENT,然后调用页面的submit方法提交页面表单。这就是为什么我们可以通过Request.Form[“__EVENTTARGET”]获取得到引发页面PostBack的控件ID的原因。
了解了__doPostBack函数后,我们可以很容易的利用它非常方便地自己触发自定义的PostBack事件。那上面也说了,大部分的控件都是调用这个方法来引了页面的PostBack,只有两个控件是例外,Button 和 ImageButton,正是因为它们不是通过调用__doPostBack来回发事件,所以通过表单隐含变量__EVENTTARGET和__EVENTARGUMENT是无法获取得到引发PostBack的Button或ImageButton的ID和参数值的,只有通过下面的方式才能得它们的实例,进而判断是哪个控件引发的PostBack的:
foreach (string str in Request.Form){
Control c = Page.FindControl(str);
if (c is Button){
control = c;
break;
}
}
为什么能通过枚举Request.Form集合的Key值,查找到的回发事件源呢?在这里Button和ImageButton又有一些不同。Button控件引发的PostBack,会将Button本身的ID作为Request.Form的一个Key,它的Value是Button的Text属性值,回传给服务器,这样服务器就可以通过枚举Request.Form的Key值,去查找出控件实例,判断是否为Button控件,进而得到是哪个控件引发的PostBack事件。而ImageButton的不同就在于,它不仅仅是用ImageButton的ID作为Request.Form的Key,它是用ImageButton的ID加上.x和.y,作为Key,在Request.Form添加两上键值对,这两个键值对的值应该是标识ImageButton的图片大小。同样的,了解了这个规律后,我们仍然可以通过一定的方式得到是否是由ImageButton引发的PostBack。
总结:理解并掌握__doPostBack原理对我们更加了解Page的事件模型有非常大的帮助,并且也是我们进一步利用好页面的PostBack事件的一个重要基础。在整个asp.Net页面PostBack模型中,只有Button和ImageButton是个例外,其它的控件都是一样的,也就是使用__doPostBack函数。在当我们需要通过__EVENTTARGET取得到事件源控件的话,这点是特别要注意的。
深入理解asp.net中的 __doPostBack函数的更多相关文章
- 理解asp.net中DropDownList编辑数据源,绑定数据库数据。
一.理解asp.net绑定数据库 终于学习到了连接数据库部分的内容,杨中科老师视频看起来挺轻松的,如果是高清版就更ok了. 我发现我学习新的编程语言会有一个特点,都想要赶紧学习数据库,数据就是一切,有 ...
- 转:通过代码理解Asp.net4中的几种ClientIDMode设置.
转:http://www.cnblogs.com/xray2005/archive/2011/07/05/2097881.html 以前我们可以通过ClientID在JavaScript脚本中服务器端 ...
- 通过代码理解Asp.net4中的几种ClientIDMode设置.
以前我们可以通过ClientID在JavaScript脚本中服务器端控件.比如: document.getElementById("<%=控件.ClientID %>" ...
- 理解Spark RDD中的aggregate函数(转)
针对Spark的RDD,API中有一个aggregate函数,本人理解起来费了很大劲,明白之后,mark一下,供以后参考. 首先,Spark文档中aggregate函数定义如下 def aggrega ...
- asp.net core 3.1 入口:Program.cs中的Main函数
本文分析Program.cs 中Main()函数中代码的运行顺序分析asp.net core程序的启动,重点不是剖析源码,而是理清程序开始时执行的顺序.到底用了哪些实例,哪些法方. asp.net c ...
- 理解和使用 JavaScript 中的回调函数
理解和使用 JavaScript 中的回调函数 标签: 回调函数指针js 2014-11-25 01:20 11506人阅读 评论(4) 收藏 举报 分类: JavaScript(4) 目录( ...
- js中的回调函数的理解和使用方法
js中的回调函数的理解和使用方法 一. 回调函数的作用 js代码会至上而下一条线执行下去,但是有时候我们需要等到一个操作结束之后再进行下一个操作,这时候就需要用到回调函数. 二. 回调函数的解释 因为 ...
- 简单理解ECMAScript2015中的箭头函数新特性
箭头函数(Arrow functions),是ECMAScript2015中新加的特性,它的产生,主要有以下两个原因:一是使得函数表达式(匿名函数)有更简洁的语法,二是它拥有词法作用域的this值,也 ...
- asp.net中调用javascript自定义函数的方法(包括引入JavaScript文件)总结
通常javascript代码可以与HTML标签一起直接放在前 端页面中,但如果JS代码多的话一方面不利于维护,另一方面也对搜索引擎不友好,因为页面因此而变得臃肿:所以一般有良好开发习惯的程序员都会把 ...
随机推荐
- 《Advanced Bash-scripting Guide》学习(五):检查一个可执行文件是否存在
本文所选的例子来自于<Advanced Bash-scripting Gudie>一书,译者 杨春敏 黄毅 ABS书上的例子是这样的: #!/bin/bash echo hello;ech ...
- 神经网络卷积层 要回计算output的维度 input 28 卷积是3x3 则output是26 但是channel是卷积核的数量
model = Sequential() model.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=input_s ...
- LeetCode OJ:Binary Tree Right Side View(右侧视角下的二叉树)
Given a binary tree, imagine yourself standing on the right side of it, return the values of the nod ...
- 设置SSH自动登陆(免密码,用户名)
设置SSH自动登陆(免密码,用户名) 1.创建公钥.公钥 ssh-keygen -t rsa 无视它出来的任何提示,欢快的一路回车到底吧. 2.把公钥 id_rsa.pub 复制到远程机器的 ...
- ASP.net之HttpModel
HttpModule是向实现类提供模块初始化和处置事件.当一个HTTP请求到达HttpModule时,整个ASP.NET Framework系统还并没有对这个HTTP请求做任何处理,也就是说此时对于H ...
- bzoj 5210 最大连通子块和——动态DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=5210 似乎像bzoj4712一样,依然可以用别的方法做.但还是只写了动态DP. 当然是dp[ ...
- laravel vendor目录的安装
- hihoCoder#1322(树的判定)
时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个包含 N 个顶点 M 条边的无向图 G ,判断 G 是不是一棵树. 输入 第一个是一个整数 T ,代表测试数据的组 ...
- mina在spring中的配置多个端口
本次练习中是监听2个端口 applicationContext-mina.xml: <?xml version="1.0" encoding="UTF-8" ...
- Druid 0.2.25版本hive jdbc 不支持 conn.getHoldability() 兼容处理问题
背景: 用Druid做Oracle的连接池感觉还不错,近日新项目要用Hive,故而也想使用Duid来做Hive的连接池.试了试果真可以,也没报错.但是,过了一段时间,同样的代码却出问题了.离奇的是我同 ...