惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园_首页
雷峰网
雷峰网
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
WordPress大学
WordPress大学
腾讯CDC
T
Tailwind CSS Blog
A
About on SuperTechFans
H
Hackread – Cybersecurity News, Data Breaches, AI and More
The GitHub Blog
The GitHub Blog
T
The Blog of Author Tim Ferriss
G
Google Developers Blog
The Cloudflare Blog
D
DataBreaches.Net
Recent Announcements
Recent Announcements
Engineering at Meta
Engineering at Meta
B
Blog
博客园 - 聂微东
阮一峰的网络日志
阮一峰的网络日志
月光博客
月光博客
博客园 - 司徒正美
MongoDB | Blog
MongoDB | Blog
Google DeepMind News
Google DeepMind News
Apple Machine Learning Research
Apple Machine Learning Research

博客园 - zengjun

IE11浏览器中的My97日历控件刷新后无法打开问题解决办法 js模拟Map对象,实现key---value 10 个Javascript框架和丰富的UI组件 获取经纬度之间的距离的SQL函数(转) ASP.NET使用FCKEditor_2.6.6与FCKeditor.Net_2.6.3配置(转载) JS的正则表达式 按指定长度截取字符串(以字节计算长度) CSS IE6,IE7,FF兼容性(转)让你的IE7和IE6友好共存(转) DataGrid中选中checkbox时,该行颜色改变(转) js获取浏览器高度和宽度值(转) ASP.NET 让控件获取焦点及设置输入法全角半角或无效 调用C++开发的DLL报内存异常错误 Gridview设置DataFormatString (转) .NET三层经典架构PetShop3.0说明之表现层 .NET三层经典架构PetShop3.0说明连载一(转) 用ASP.Net2.0开发多语言系统 邮件收发类 永远不要跟父母说的几句话(转) C#泛型集合揽胜(转)
asp.net页面回传与js调用服务端事件、PostBack的原理详解(转)
zengjun · 2008-07-23 · via 博客园 - zengjun

Asp.net中服务端控件事件是如何触发的

一.   WebControls中的Button HtmlControls中的TypesubmitHtmlInputButton

这两种按钮最终到客户端的表现形式为:<input type="submit" value="Submit">,这是Form表单的提交按钮,点击以后会作为参数发送到服务端,参数是这样的:

控件的name属性=控件的value值,对应上面的例子就是:Submit1= Submit。服务器端会根据接收到的控件的name属性的这个key来得知是这个按钮被点击了,从而在服务端触发这个按钮的点击事件。

二.   HtmlControls 中的 TypebuttonHtmlInputButton 和其它所有的控件事件,比如LinkButton点击,TextBoxChange事件等等:

这些事件在客户端产生后会经过一个统一的机制发送到服务端。

1.首先asp.net页框架会使用两个Hidden域来存放表示是哪个控件触发的事件,以及事件的参数:

<!―表示触发事件的控件,一般是这个控件的name -->

<input type="hidden" value="" />

<!―表示触发事件的参数,一般是当某个控件有两个以上的事件时,用来区别是哪个事件 -->

<input type="hidden" value="" />

2.服务端会生成一个jscript的方法来处理所有这些事件的发送,这段代码是:

<script language="javascript" type="text/javascript">

    function __doPostBack(eventTarget, eventArgument)

    {

        var theform = document.WebForm2;

        theform.__EVENTTARGET.value = eventTarget;

        theform.__EVENTARGUMENT.value = eventArgument;

        theform.submit();

    }

</script>  

3.每个会引发服务端事件的控件都会在响应的客户端事件中调用上面的代码:

比如,HtmlControls 中的 TypebuttonHtmlInputButton的点击事件

<!―客户端的点击事件调用__doPostBackeventTarget 参数为'Button2',表示是name'Button2’控件触发的事件,eventArgument 为空,表示这个TypebuttonHtmlInputButton只有一个客户端触发的服务端事件-->

<input language="javascript" Button2','')" type="button" value="Button" />

又比如,TextBox控件的Change事件

<!―客户端的onchange事件调用__doPostBackeventTarget 参数为’TextBox1’,表示是name’TextBox1’控件触发的事件,而TextBox控件只有一个客户端触发的服务端事件TextChanged,故服务器就会去触发这个TextBoxTextChanged事件->

<input type="text" TextBox1','')" language="javascript" />

4.客户端触发事件后调用__doPostBack方法,将表示触发的控件源的eventTarget 和事件参数eventArgument分别付给两个隐藏域__EVENTTARGET__EVENTARGUMENT,然后提交Form,在服务端根据__EVENTTARGET__EVENTARGUMENT来判断是哪个控件的什么事件触发了。

第二章 PostBack的原理

__doPostBack是一个纯粹并且是非常简单的javascript函数,大部分的页面PostBack都是由它触发的。注意,这里是大部分,因为只有两个Web Server Control    会自己触发页面的PostBack,其它的所有控件都是通过__doPostBack函数触发页面的PostBack,那先来看一下这个函数的定义吧:

CODE1:

<input type="hidden" value="" />

<input type="hidden" value="" />

function __doPostBack(eventTarget, eventArgument) {

if (!theForm.onsubmit || (theForm.onsubmit() != false)) {

theForm.__EVENTTARGET.value = eventTarget;

theForm.__EVENTARGUMENT.value = eventArgument;

theForm.submit();

}

}

通过上面的代码可以看到,__doPostBack带有两个参数,eventTarget是标识将要引发页面PostBack的控件IDeventArgument参数提供了在引发页面PostBack事件时所带的额外参数。当然这个函数被函数时,这两个参数的值将赋值给页面的两个隐含变量__EVENTTARGET__EVENTARGUMENT,然后调用页面的submit方法提交页面表单。这就是为什么我们可以通过Request.Form[“__EVENTTARGET”]获取得到引发页面PostBack的控件ID的原因。

了解了__doPostBack函数后,我们可以很容易的利用它非常方便地自己触发自定义的PostBack事件。那上面也说了,大部分的控件都是调用

第三章 Button PostBack做法

引了页面的PostBack,只有两个控件是例外,Button ImageButton,正是因为它们不是通过调用__doPostBack来回发事件,所以通过表单隐含变量__EVENTTARGET__EVENTARGUMENT是无法获取得到引发PostBackButtonImageButtonID和参数值的,可通过下面的方式实现

1)在页面中加如 LinkButton ,页面就会在页面中加载POSTBACK所需的JS

<input type="hidden" value="" />

<input type="hidden" value="" />

function __doPostBack(eventTarget, eventArgument) {

if (!theForm.onsubmit || (theForm.onsubmit() != false)) {

theForm.__EVENTTARGET.value = eventTarget;

theForm.__EVENTARGUMENT.value = eventArgument;

theForm.submit();

}

}

2)利用GetPostBackEventReference给客户端生成__doPostBack()
如:

比如前台页面

<asp:Button id="Button1" runat="server" Text="Button"></asp:Button>

1

<href="#" onclick="document.getElementById('Button1').click()">触发服务器端按钮事件</a>

2
利用GetPostBackEventReference给客户端生成__doPostBack()
前台

<href="#" onclick="<%=PostBack()%>">触发服务器端按钮事件</a>

后台

protected string PostBack()
        {
            
return this.Page.GetPostBackEventReference(this.Button1,"haha");
        }

通过__EVENTARGUMENT="haha"可以判断是不是点了那个链接的PostBackButton1的按钮事件这么写:

if(Request["__EVENTARGUMENT" ]=="haha")
            {
                Response.Write("
这个是链接的PostBack");
            }
            
else
            {
                Response.Write("
这个不是链接的PostBack");
            }

Bug

问题:『使用__doPostBack会导致』

回发或回调参数无效。在配置中使用 <pages enableEventValidation="true"/> 或在页面中使用 <%@ Page EnableEventValidation="true" %> 启用了事件验证。出于安全目的,此功能验证回发或回调事件的参数是否来源于最初呈现这些事件的服务器控件。如果数据有效并且是预期的,则使用 ClientScriptManager.RegisterForEventValidation 方法来注册回发或回调数据以进行验证。

问题分析及解决方案:『来源网络』

这个要具体分析。本来这个措施是asp.net2.0用来防止客户端欺诈服务器端的。例如本来输出到客户端的一个事件被触发时需要回发的命令是“__doPostback('ctl01$abc','user_1')”的,如果采取采取手段把回发参数由 user_1 改为 user_5 了,服务器端会重新核对输出的是不是user_5,发现和这个页面上一个输出的脚本不一致,就会产生这个异常。

但是,很多程序员写的程序按照过去的习惯(或者按照更加高级灵活的设计例如一些Ajax组件)没有考虑这个问题或者是忽略这个欺诈的可能性,写的程序可能会修改参数或者修改目标控件。

因此这样具体问题具体分析。不太可能跟浏览器距离服务器的远近有关,应该还是编程逻辑问题。你应该对出异常的画面以及所使用的数据进行分析。有时候,经常也需要将这个参数设置为false,放弃安全管理