[ASP.NET]從ASP.NET Postback機制,到POST/GET方法

寫這篇博客的起源來自於本身最近在學習ASP.NET時對於 PostBack機制的困惑。由於本身在解決困惑地同時,會不斷產生新的疑問,所以博客最後深刻到了http 包的格式和Internet所使用的TCP/IP模型,算是來了一堂基礎複習課。但我相信這些基礎的牢固性,會影響到web方向的深刻學習,所以整理成文,便於複習,便於探討。javascript

寫博的時候並無將http協議包格式等底層的東西調整到最前面寫,由於我以爲既然我是這樣思考的,何不這樣呈現?爲了便於描述,我用下圖這棵樹表示寫這篇博文的思路,IsPostBack是表面的引發疑問的葉子,順着這片葉子,能夠逐漸追溯到http協議這個樹幹。「Post與Get方法」那一塊被安排在樹幹上,是由於從這裏開始,觸及了Web開發的主體;枝葉上的ASP.NET部分,只是基於這個主體又加入本身的技術的延伸。別的技術好比JSP,Struts等Java方向的技術,也是基於這個主體的另外一種技術方向的延伸,所以它們都會像樹枝同樣,從主幹上發散開。html

博文中有任何以爲不對的地方,歡迎在留言中和我探討。畢竟我也只是剛接觸Web不久的Fresh Man,行文之時,心下惴惴,所以歡迎指出錯誤和討論。前端

PostBack機制

什麼是Postback?IsPostBack的做用是什麼?java

PostBack機制是ASP.NET特有的機制,爲何說特有,咱們從web請求和響應提及。web

web的基本原理就是請求和響應。以asp爲例,Browser端的HTML文本,以及javascript代碼,運行後向server端發送request,server端的.asp腳本,接受request,處理後發出respond。這種server端script和client端script交互,完成一次次對於用戶操做(提交表單,載入新的URL)的響應。ajax

以一個html文件和asp文件爲例:後端

html代碼:瀏覽器

<!DOCtype html PUBLIC "-//W3C//DTD XhTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>order</title></head>
<body>
<h2>Form Example</h2>
<p>
Please input and submit
<form method="POST" ACTION="Response.asp">
<p>
姓: <input NAME="fname" SIZE="48"/>
<p>
名: <input NAME="lname" SIZE="48"/>
<p>
稱呼: <input NAME="title" type=RADIO VALUE="先生"/>先生
<input NAME="title" type=RADIO VALUE="女士"/>女士
<p><input type=SUBMIT VALUE="提交"/><input type=RESET VALUE="清除"/>
</form>
</body>
</html>
Response.asp腳本代碼(VB語言)
<HTML>
<HEAD></HEAD>
<BODY>
<%
Title = Request.Form("title")
LastName = Request.Form("lname")
If Title = "先生" Then
Response.Write LastName & "先生"
ElseIf Title = "女士" Then
Response.Write LastName & "女士"
Else
Response.Write Request.Form("fname") & " " & LastName
End If %>
</BODY>
</HTML>

能夠看到HTML文件的form控件中,"action"屬性指定了form提交後處理它的Server端腳本。安全

而在ASP.NET系統中,咱們沒有Client端和Server端腳本,咱們只有aspx文件,而aspx也會被Render爲HTML,在Client端經過瀏覽器顯示,由於瀏覽器只能識別HTML標籤。服務器

下面的例子引自Artech的淺談ASP.NET的Postback,這篇文章講解了Postback的實現方式,簡單說來:Render以後的HTML會自動加入一個form,其中用hidden的input來存儲id和事件參數。在__Postback這個函數中,form中的內容會被提交。Artech所給的aspx代碼在Browser端的呈現出來的源碼以下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>
            Test Page
        </title>
    </head>
    <body>
        <form name="form1" method="post" action="Default.aspx" id="form1">
            <div>
                <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=" />
            </div>

<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>

<div>
<span id="LabelMessage" style="color:Red;"></span>
</div>
<div>
    <input type="submit" name="Button1" value="Button1" id="Button1" />
    <input type="button" name="Button2" value="Button2" onclick="javascript:__doPostBack('Button2','')" id="Button2" />
    <input type="button" name="Button3" value="Button3" onclick="javascript:__doPostBack('Button3','')" id="Button3" />
</div>
</form>
</body>
</html>

以上代碼在Artech博文中也能夠找到,我把它貼過來,以方便引述。這段代碼是Default.aspx被render到browser端的html源碼,Postback的實現機制就是定義了一個form,這個Form中包含隱藏的input,從而保存須要post的值,那麼,向哪裏post?Form中"action"屬性指定了post的目標,那這裏呢?咱們能夠看到其值爲"Default.aspx",也就是它本身。這和上面那個ASP的例子中是不一樣的。

個人理解是:所謂Postback,是指在ASP.NET機制中,不是Client端發post請求到server端腳本,在這個機制中,aspx被render到browser後,其Form的post目標依然是這個aspx。Postback由此得名,由於post回來了。。

所以當咱們觸發網頁的按鈕時,若此按鈕涉及到後臺操做(在後端有C#響應代碼,而非僅僅調用前端javascript函數),aspx頁面便會從新加載,由於Postback觸發了它。(這句話待商榷,我對Postback與page life cycle瞭解再深入些後,會再編輯這句話)。

這個機制所須要解決的第一個問題是:當開發人員編寫代碼時,aspx的加載有兩種緣由:點擊按鈕觸發post來讓aspx加載;用戶輸入url來加載aspx。對於不一樣的緣由,可能開發人員但願代碼進入不一樣的處理邏輯。IsPostback這個ASP.NET所給的變量,就是用來給developer肯定是否這個網頁是由於postback而加載,而是經過輸入url或者刷新頁面的方式來加載。

最簡單的例子,Page_Load()方法裏常常會 if(!IsPostBack) BindForm();//給表單全部控件賦值的方法。意思是提交後我就不綁定表單了,而是走Click的具體事件方法。

而IsPostBack是什麼時候被賦值的,ASP.NET代碼中是根據什麼條件來判斷是不是postback的網頁,這一個樹枝暫時尚未研究下去,若是能有前輩能在留言中給我一些線索的話,感激涕零 :)

有關於Page_Load()方法,它是ASP.NET中的網頁載入過程當中page load事件的默認響應函數,具體請參見:

ASP.NET 頁生命週期概述  以及 [ASP.NET]Page Life Cycle整理

所以Postback的機制本質實現實際上是form的post,那麼post和get,這些具體是什麼?

POST與GET方法

正如以前所說,web實際就是request與respond的交互,那麼,這些request與respond,其實就是http包。

對於一個Request,它可能不只僅是一個要求載入頁面的request,也多是要求發送一些數據的request,或者要求刪除服務端一些數據的request,如何區分這些request?http給request定義了四個謂詞:POST,GET,PUT,DELETE。從名字就能夠看出來他們的功用,分別對應着改,查,增,刪。

而最常使用的是GET與POST。

他們的共同點和區別在哪裏?

共同點是:GET POST其實均可以實現向服務器傳送數據。在HTML中,自己表單form的提交就有兩種方式,一種是get的方法,一種是post 的方法。而這兩種方法保存參數的方式是不一樣的,若是使用Fiddler或其餘的http包查看工具,能夠發現post方法提交的Form,其參數存在body中,而get方法提交的form,其參數則直接加入到url的後面。

經過包來看二者之間本質的差異的例子,能夠參見淺談 HTTP Method:表單中的 GET 與 POST 有什麼差別?

經過輸入url來訪問頁面,其request都是get。

二者特性上的差異:form方式由於是將內容放在body中發過去,而get僅僅是發一個get請求過去,內容在url中,所以速度比post快,而安全性則低於post。

GET的response會被cache,而POST的response不會。由於GET的初衷就是獲取內容,所以能夠經過cache來存儲不變的內容,而POST則是用來提交內容,其響應基於所提交的內容可能不斷變化。

二者之間其餘差異參見下圖,圖來自[HTTP]Http GET、POST Method

有一篇文章提到了在使用Ajax時,POST會比GET慢數倍,各位有興趣能夠看一下:打破沙鍋-AJAX POST比GET效率差?

以前提到既然request和response實際就是HTTP包,那POST與GET這些謂詞又是如何在包中呈現的?

POST與GET報文格式

 以Artech的那個例子爲例,那個例子若是運行起來,會看到三個按鈕,點擊其中一個,會顯示哪一個按鈕的click被fire了:

點擊Button3後,request與response在fiddler中的內容如圖:

在fiddle中,能夠看到POST就出如今Request的第一行中。

Response的Header的內容是:HTTP/1.1 200 OK

 

 一個http請求報文的格式以下圖 (圖片來自計算機網絡應用層之HTTP協議)

 分爲請求行(Request line),首部行(Header line),空行(Brank line)和實體(body),謂詞方法的位置就在請求行的開頭。

HTTP響應respond的報文格式以下:

其中200爲狀態碼,表示請求成功。返回內容在實體中呈現,好比以前fiddler的截圖,響應包中的內容就是原先那個HTML的內容,也就是說,瀏覽器收到這個response後,用戶會看到整個頁面被刷新了一下。

咱們知道了http的報文格式,那什麼是HTTP協議?

HTTP協議

HTTP是HyperText Transfer Protocol即超文本傳輸協議的縮寫,是Web應用層協議之一。

在說這個以前,先提幾個HTTP的特性,這部分引用了Tank的 HTTP協議詳解 中部份內容

HTTP協議是無狀態的:同一個客戶端的此次請求和上次請求是沒有對應關係,對http服務器來講,它並不知道這兩個請求來自同一個客戶端。 爲了解決這個問題, Web程序引入了Cookie機制來維護狀態。引入了ViewState來存儲控件內容或者用戶自定義信息。

關於Cookie的介紹,讀寫方式,以及它在ASP.NET form authentication中所起的做用,參見:Fish Li的細說Cookie

關於ViewState:個人理解是一種在用戶端存儲控件內容和一些開發人員自定義內容的機制。其實現方式是在用戶端的HTML代碼中插入名字爲"__ViewState"的hidden input,那些須要存儲的內容,都通過Base64編碼後以字符串的形式存儲在這個hidden input中。由於是以字符串的形式存儲在客戶端的HTML文件中,所以屬於長期儲存,不會自動過時或消失,用戶甚至能夠拷貝下來保存。更多內容,參見 [.NET] ASP.NET 狀態管理(State Management):ViewState

打開一個網頁須要瀏覽器發送不少次Request:

1. 當你在瀏覽器輸入URL http://www.cnblogs.com 的時候,瀏覽器發送一個Request去獲取 http://www.cnblogs.com 的html.  服務器把Response發送回給瀏覽器.

2. 瀏覽器分析Response中的 HTML,發現其中引用了不少其餘文件,好比圖片,CSS文件,JS文件。

3. 瀏覽器會自動再次發送Request去獲取圖片,CSS文件,或者JS文件。

4. 等全部的文件都下載成功後。 網頁就被顯示出來了。

 

因爲HTTP是使用TCP做爲其運輸協議的,所以http協議也須要鏈接,也須要三次握手的過程。

TCP鏈接分爲持久鏈接和非持久鏈接:

在非持久鏈接的狀況下,服務器在發送響應後,關閉TCP鏈接。咱們定義往返時間RTT爲一個小分組從客戶機到服務器再回到客戶所花費的時間。因此RTT包括分組傳播時延、排列時延以及分組處理時延。

若http採用非持久鏈接時,咱們能夠估算出完成一次傳輸所消耗的時間:完成了三次握手的前兩部分後,客戶機將三次握手的第三部分(確認)與一個HTTP請求報文結合起來發送到該TCP鏈接。一旦請求報文到達服務器,服務器向該TCP鏈接發送HTML文件。從上面的描述,咱們能夠知道,對於一個非持久鏈接,請求一個HTTP請求/響應須要的總時間爲兩個RTT+服務器傳輸HTML文件的時間,也就是兩個來回所耗的時間加上傳輸時間。

在持久鏈接狀況下,服務器在發出響應後讓TCP鏈接繼續打開着。同一對客戶/服務器之間的後續請求和響應能夠經過這個鏈接發送。整個Web頁面(上例中爲包含一個基本HTMLL文件和10個圖像的頁面)自不用說能夠經過單個持久TCP鏈接發送:甚至存放在同一個服務器中的多個Web頁面也能夠經過單個持久TCP鏈接發送。一般,HTTP服務器在某個鏈接閒置一段特定時間後關閉它,而這段時間一般是能夠配置的。
持久鏈接分爲不帶流水線(without pipelining)和帶流水線(with pipelining)兩個版本。若是是不帶流水線的版本,那麼客戶只在收到前一個請求的response後才發出新的request。帶流水線則是不等到response就發下一個request。這樣,在密集請求的狀況下,不帶流水線的每個請求響應過程都比帶流水線的慢一個RTT,由於後一個基本沒必要等,前一個至少每次等一個RTT。
 
HTTP/1.1的默認模式使用帶流水線的持久鏈接。這種狀況下,HTTP客戶每碰到一個引用就當即發出一個請求,於是HTTP客戶能夠一個接一個緊挨着發出各個引用對象的請求。
 
HTTP是Web應用層協議之一,那麼它在整個網絡之中如何傳遞呢?

網絡分層結構

咱們知道互聯網的框架主要是兩種:OSI的七層框架,和TCP/IP體系結構。而Internet網絡體系結構以TCP/IP爲核心。基於TCP/IP的參考模型將協議分紅四個層次。

這兩種模型的對應關係如圖,圖片來自網絡互聯參考模型(詳解)

而咱們以前應用層的http報文,從最高層往下經歷層層封裝,最後到達最底層轉換爲01流。發往目的地,中間會通過交換機和路由器的中轉,解包,確認下一個轉發地址後再次封包轉發。以下圖 (圖片來自網絡互聯參考模型(詳解))

 

相關文章
相關標籤/搜索