Form(表單)對於每個WEB開發人員來說,應該是再熟悉不過的東西了,可它卻是頁面與WEB伺服器互動過程中最重要的資訊來源。 雖然Asp.net WebForms架構為了協助我們簡化開發工作,做了很完美的封裝,讓我們只需要簡單地使用服務端控制項就可以直接操作那些 HTML表單元素了。但我認為瞭解一些基礎的東西,可以使我們不必束縛在WebForms架構上,以及遇到一些奇怪問題時, 可以更從容地解決它們。但在asp.net下開發,卻使我們無法深入表單。(平常我們對from的理解,要把伺服器控制項寫在from裡面,並且加上runat="server")
<form id="form1" runat="server"> <div> <asp:Label ID="lb1" runat="server"></asp:Label> </div> </form>
但是from在html下如何操作的呢?
<form action="Handler1.ashx" method="post" ><p>客戶名稱: <input type="text" name="CustomerName" style="width: 300px" /></p><p>客戶電話: <input type="text" name="CustomerTel" style="width: 300px" /></p><p><input type="submit" value="提交" /></p>
在這張圖片中,我們可以看到瀏覽器確實將請求發給了我前面在action中指定的地址,且以POST形式發出的。 表單的二個控制項的輸入值放在請求體中,且做了【編碼】處理,編碼的方式用要求標頭Content-Type說明, 這樣,當服務端收到請求後,就知道該如何讀取請求的內容了。 注意:表單的資料是以name1=value1&name2=value2 的形式提交的,其中name,value分別對應了表單控制項的相應屬性。
提交方式:在前面的範例程式碼中,我為form指定了method="post",這個提交方法就決定了瀏覽器在提交資料時,通過什麼方式來傳遞它們。
如果是【post】,那麼表單資料將放在請求體中被發送出去。
如果是【get】,那麼表單資料將會追加到查詢字串中,以查詢字串的形式提交到服務端。
建議:表單通常還是以post方式提交比較好,這樣可以不破壞URL,況且URL還有長度限制。
資料的編碼:前面我將瀏覽器的請求細節用Fiddler做了個,從這個圖中我們可以看到:控制項輸入的內容並不是直接發送的, 而是經過一種編碼規則來處理的。目前基本上只會只使用二種編碼規則:application/x-www-form-urlencoded(預設) 和 multipart/form-data 。接收時,告訴伺服器要用什麼方式讀取資料。
在接收頁面我們可以通過表單控制項的name屬性訪問Request.Form就可以了。
using System;using System.Collections.Generic;using System.Linq;using System.Web;namespace test2{ /// <summary> /// Handler1 的摘要說明 /// </summary> public class Handler1 : IHttpHandler { public void ProcessRequest(HttpContext context) { string name = context.Request.Form["CustomerName"]; string tel = context.Request.Form["CustomerTel"]; context.Response.ContentType = "text/plain"; context.Response.Write(name+":"+tel); } public bool IsReusable { get { return false; } } }}
運行結果:
lingx:112233
那麼提交表單時會提交哪些資料呢?
瀏覽器並不是將所有的表單控制項全部發送到伺服器的,而是會尋找所有的【成功控制項】,只將這些成功控制項的資料發送到服務端, 什麼是成功控制項呢?
簡單地來說,成功控制項就是:每個表單中的控制項都應該有一個name屬性和”當前值“, 在提交時,它們將以 name=value 的形式做為提交資料的一部分。
對於一些特殊情況,成功控制項還有以下規定:
1. 控制項不能是【禁用】狀態,即指定【disabled="disabled"】。即:停用控制項將不是成功控制項。
2. 如果一個表單包含了多個提交按鍵,那麼僅當使用者點擊的那個提交按鈕才算是成功控制項。
3. 對於checkbox控制項來說,只有被使用者勾選的才算是成功控制項。
4. 對於radio button來說,只有被使用者勾選的才算是成功控制項。
5. 對於select控制項來說,所有被選擇的選項都做為成功控制項,name由select控制項提供。
6. 對於file上傳檔案控制項來說,如果它包含了選擇的檔案,那麼它將是一個成功控制項。
此外,瀏覽器不會考慮Reset按鈕以及OBJECT元素。
如何提交表單的呢?
在form裡面點擊button就會提交表單!那多個按鈕的時候,如何判斷每個按鈕的做用呢?
方法1:根據【成功控制項】定義,我們設定按鈕的name,在服務端用name來區分哪個按鈕的提交:
HTML代碼
<form action="Handler1.ashx" method="post" ><p>客戶名稱: <input type="text" name="CustomerName" style="width: 300px" /></p><p>客戶電話: <input type="text" name="CustomerTel" style="width: 300px" /></p><p><input type="submit" name="btnSave" value="儲存" /> <input type="submit" name="btnQuery" value="查詢" /></p>
服務端處理代碼
using System;using System.Collections.Generic;using System.Linq;using System.Web;namespace test2{ /// <summary> /// Handler1 的摘要說明 /// </summary> public class Handler1 : IHttpHandler { public void ProcessRequest(HttpContext context) { if (string.IsNullOrEmpty(context.Request.Form["btnSave"]) == false) { // 儲存的處理邏輯 string name = context.Request.Form["CustomerName"]; string tel = context.Request.Form["CustomerTel"]; context.Response.ContentType = "text/plain"; context.Response.Write(name + ":" + tel); } if (string.IsNullOrEmpty(context.Request.Form["btnQuery"]) == false) { // 查詢的處理邏輯 context.Response.Write("btnQuery"); } } public bool IsReusable { get { return false; } } }}
方法2:我將二個按鈕的name設定為相同的值(根據前面的成功控制項規則,只有被點擊的按鈕才會提交),在服務端判斷value,範例程式碼如下:
<form action="Handler1.ashx" method="post" ><p>客戶名稱: <input type="text" name="CustomerName" style="width: 300px" /></p><p>客戶電話: <input type="text" name="CustomerTel" style="width: 300px" /></p><p><input type="submit" name="submit" value="儲存" /> <input type="submit" name="submit" value="查詢" /></p>
string action = context.Request.Form["submit"]; if (action == "儲存") { // 儲存的處理邏輯 } else if (action == "查詢") { // 查詢的處理邏輯 }