1. 程式人生 > >__doPostBack方法解析 __VIEWSTATE __EVENTTARGET __doPostBack __EVENTARGUMENT

__doPostBack方法解析 __VIEWSTATE __EVENTTARGET __doPostBack __EVENTARGUMENT

本質 隱藏 target 彈出窗口 mman 原因 判斷 num lai

關於這個的另一篇博客:http://www.cnblogs.com/Silicon-Fado/archive/2009/04/21/1440437.html

__VIEWSTATE:頁面狀態信息在客戶端的存儲(ViewState中存儲的信息, EnableViewState="true"的控件狀態信息).
__EVENTTARGET:頁面回傳觸發事件 頁面回傳觸發事件:

__doPostBack(‘Button2‘,‘‘)表示調用按鈕Button2在後端的所對應的單擊事件 控件回傳觸發事件:

__doPostBack(‘TEST1$Button1‘,‘‘)表示調用TEST1控件中的Button1按鈕的Click方法
__EVENTARGUMENT:頁面回傳觸發事件時所帶的參數 如:__doPostBack(‘Button1‘,‘aa‘)在後端可以使用Request.Form["__EVENTARGUMENT"]來取得
.net自動生成的一些客戶端的代碼 用來回傳數據和自己帶的一些腳本函數
=====================================================================

今天工作時遇到一個需要根據Gridview具體內容來判斷是否彈出窗口,而Gridview中包含分頁、排序等,它們並不能直接從查詢字符串、或表單簡單的分析出。這是因為存在__doPostBack方法,以及和其緊密關聯的__ EVENTTARGET和__ EVENTARGUMENT。


function __doPostBack(eventTarget, eventArgument)的eventTarget參數是GridView控件的名字,eventArgument參數是命令字。當如果是刪除時,eventArgument參數是Delete開頭;當如果是插入時,eventArgument參數是Insert開頭;當如果是編輯時,eventArgument參數是Edit開頭;當如果是選擇時,eventArgument參數是Select開頭。

============================================================
客戶端觸發事件後調用__doPostBack方法,將表示觸發的控件源的eventTarget 和事件參數eventArgument分別付給兩個隱藏域__EVENTTARGET和__EVENTARGUMENT,然後提交Form,在服務端根據 __EVENTTARGET和__EVENTARGUMENT來判斷是哪個控件的什麽事件觸發了。

< script language="javascript">   function __doPostBack(eventTarget, eventArgument) {   var theform = document.WebForm2;   theform.__EVENTTARGET.value = eventTarget;   theform.__EVENTARGUMENT.value = eventArgument;   theform.submit();   } < /script>

=================================================================Asp.net的postback機制我們知道Asp.net輸出到客戶端時都會被轉化為HTML,頁面Render到Client後,Client的HTML代碼將包含如下代碼:

技術分享圖片
  <input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />

<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMTA0NDQ2OTE5OWRk281L4eAk7iZT10hzg+BeOyoUWBQ=" />

<script type="text/javascript">

<!-- 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>
技術分享圖片

其中隱藏字段_EVENTTARGET代表觸發事件的控件。_EVENTARGUMENT代表事件的額外參數。為了頁面能在PostBack後依然能讀取服務器控件原有的狀態數據,Asp.net中使用了ViewState技術,而ViewState技術本質上是用一個默認名稱為__VIEWSTATE的Hidden類型表單域來保存和傳遞數據(這些數據是經過了序列化後Base64編碼的字符串值)。控件的事件被Render後事件變成javascript:__doPostBack(‘Button1‘,‘‘)

例如下面的樣子

<input type="button" name="Button1" value="Button1" onclick="javascript:__doPostBack(‘Button1‘,‘‘)" id="Button1" />

===============================================================================================

這地方可看令一篇博文:http://www.cnblogs.com/Silicon-Fado/archive/2009/04/21/1440437.html

只有兩個Web Server Control 會自己觸發頁面的PostBack,其它的所有控件都是通過__doPostBack函數觸發頁面的PostBack,頁面解析時回將該類生成一個__doPostBack(eventTarget, eventArgument)方法。eventTarget是引起回送的控件的ID,eventArgument是回調參數(與控件相關的附加數據)。這兩個參數分別由隱藏的兩個表單域__ EVENTTARGET和__ EVENTARGUMENT保存。使用這兩個隱藏的表單可以查找引起頁面回送的控件ID和回送時的參數。

當你觸發__doPostBack事件時,遍歷this.Request.Form.AllKeys,你查看到這兩個隱藏的表單。

由於最終呈現給瀏覽器的內容都是html內容,采用asp.net技術也不能例外.要實現webcontrol的postback機制.只能在原來的submit上做文章。

我看到,asp.net現在頁面上添加了兩個hidden input,這兩個input分別用來存放觸發postback的control的ID和參數.這就是我們大部分人認識到的:

__doPostBack(obj1,obj2)的第一個參數是控件ID,第二個參數是postback的參數.然後就可以在後臺用Request.Form["__EVENTTARGET"]和Request.Form["__EVENTARGUMENT"]取得控件ID和參數.

很簡單就實現了看似很神奇,以為內部有什麽高深的處理的過程!如此輕巧的實現了asp.net的postback機制,佩服佩服!只要我們看懂了上邊的代碼,對__doPostBack的使用就應該不是什麽難事了.可以說__doPostBack就是這麽簡單的一回事.-_-||

不過,另外要註意的就是asp.net的webcontrols中,Button和ImgButton是異類,它們不是利用__doPostBack來實現postback的.為什麽這樣,可能因為Button在html中本來就是有觸發submit事件的功能吧.asp.net不過是要令原來html中一些不能觸發submit的東西submit,才弄出了__doPostBack來實現.對於原來就能submit的Button,又何必多此一舉呢.
如上寫法可以在後臺找到Button.為什麽這樣? 不知道,呵呵. 在Button的提交過程中,Button會將Button本身的ID作為Request.Form的一個Key,它的Value是Button的Text屬性值,回傳給服務器.所以可以在後臺循環Form.Keys取到所提交的Button,以執行相應的函數.ImgButton也差不多,不同就在於,它不是用ImageButton的ID作為Request.Form的Key,它是用ImageButton的ID加上.x和.y作為Key,在Request.Form添加兩上鍵值對,這兩個鍵值應該是對應ImageButton的圖片大小的,了解了這個規律後,我們仍然可以通過一定的方式得到是否是由ImageButton引發的PostBack.

如下面的我寫的一個簡單頁面的例子,

(1)頁面中的下拉列表呈現在hyml中是這樣的

技術分享圖片
<select name="DropDownList2" onchange="javascript:setTimeout(&#39;__doPostBack(\&#39;DropDownList2\&#39;,\&#39;\&#39;)&#39;, 0)" id="DropDownList2">

<option value="--請選擇--">--請選擇--</option>

<option value="家用家具1">家用家具1</option>

<option selected="selected" value="家用家具2">家用家具2</option>

<option value="家用家具3">家用家具3</option>

<option value="家用家具4">家用家具4</option>



</select>
技術分享圖片

可看到

onchange="javascript:setTimeout(&#39;__doPostBack(\&#39;DropDownList2\&#39;,\&#39;\&#39;)&#39;, 0)" id="DropDownList2">

此處下拉列表通過__doPostBack函數觸發頁面的PostBack,頁面解析時回將該類生成一個__doPostBack(eventTarget, eventArgument)方法。

(2)對於按鈕呢,則是這樣的

<input type="submit" name="Button1" value="確認" id="Button1" />

按鈕沒有用到__doPostBack,原因是asp.net的webcontrols中,Button和ImgButton是異類,它們不是利用__doPostBack來實現postback的.為什麽這樣,可能因為Button在html中本來就是有觸發submit事件的功能吧.asp.net不過是要令原來html中一些不能觸發submit的東西submit,才弄出了__doPostBack來實現.對於原來就能submit的Button,又何必多此一舉呢.

===================================================================================================

當按鈕被點擊後,觸發了__doPostBack事件,_doPostBack事件把表單提交給Server, Server端通過__EVENTTARGET這個hidden field的值找到對應的Server端的Control.接下來Server查看Control是否實現調用Page的RaisePostBackEvent,這個函數的定義如下:

技術分享圖片
protected virtual void RaisePostBackEvent(IPostBackEventHandler sourceControl, string eventArgument)

{

sourceControl.RaisePostBackEvent(eventArgument);

}
技術分享圖片

函數調用本控件內的

技術分享圖片
protected virtual void RaisePostBackEvent(string eventArgument)

{

base.ValidateEvent(this.UniqueID, eventArgument);

iif (this.CausesValidation)

{

this.Page.Validate(this.ValidationGroup);

}

this.OnClick(EventArgs.Empty);

this.OnCommand(new CommandEventArgs(this.CommandName, this.CommandArgument));

}

__doPostBack方法解析 __VIEWSTATE __EVENTTARGET __doPostBack __EVENTARGUMENT