這是我一年前寫的一個用C#模擬以POST方式提交表單的代碼,現在記錄在下面,以免忘記咯。那時候剛學C#~忽忽。。很生疏。。代碼看上去也很幼稚 臃腫不堪
#region 內容添加函數(Contentinsert)
public string Contentinsert(string bookID, string bookTitle, string bookContent,string taskUrl,string Ztagend)
{
string uriString = "這里是取VIEWSTATE等值的頁面";
//如果是asp.net頁面,最好是先取到VIEWSTATE和EVENTVALIDATION值一並提交
///////////////////////////////////////
// 打開指定的頁面
///////////////////////////////////////
XMLRW UpdateBook = new XMLRW();
WebClient webClient = new WebClient();
byte[] responseData = webClient.DownloadData(uriString);
string srcString = Encoding.UTF8.GetString(responseData);
///////////////////////////////////////
// 填寫頁面並提交
///////////////////////////////////////
webClient = new WebClient();
webClient.Headers.Add("Content-Type", "application/x-www-form-urlencoded"); //定義關聯的標頭
// 獲取頁面的 VeiwState 這個值和EventValidation 的值在這里用於數據接收頁接收數據
string viewStateFlag = "id=\"__VIEWSTATE\" value=\""; //動態抓取__VIEWSTATE的值
int i = srcString.IndexOf(viewStateFlag) + viewStateFlag.Length;
int j = srcString.IndexOf("\"",i);
string viewState = srcString.Substring(i, j-i);
// 獲取頁面的 EventValidation 這個值和EventValidation 的值在這里用於數據接收頁接收數據
string eventValidationFlag = "id=\"__EVENTVALIDATION\" value=\""; //動態抓取__EVENTVALIDATION\的值
i = srcString.IndexOf(eventValidationFlag) + eventValidationFlag.Length;
j = srcString.IndexOf("\"", i);
string eventValidation = srcString.Substring(i, j - i);
//獲取頁面的章數
string viewmenuid = "<input name=\"txt_menuid\" type=\"text\" value=\""; //動態抓取__VIEWSTATE的值
i = srcString.IndexOf(viewmenuid) + viewmenuid.Length;
j = srcString.IndexOf("\"",i);
string txt_menuid = srcString.Substring(i, j-i);
/* 提交按鈕的文本
string submitButton = "提交";
* 這句代碼主要用於當數據接收頁面是button的情況
* */
bookTitle = System.Web.HttpUtility.UrlEncode(bookTitle);
bookContent = System.Web.HttpUtility.UrlEncode(bookContent);
viewState = System.Web.HttpUtility.UrlEncode(viewState);
eventValidation = System.Web.HttpUtility.UrlEncode(eventValidation);
txt_menuid = System.Web.HttpUtility.UrlEncode(txt_menuid);
// 要提交的字符串數據。格式形如:user=uesr1&password=123
//下面開始執行數據的提交 當提交沒有錯誤將返回提交后的頁面代碼回來
string postString = "txt_title=" + bookTitle + "&txt_content=" + bookContent + "&txt_menuid=" + txt_menuid + "&cmdSaveConn.x=0&cmdSaveConn.y=0" + "&__VIEWSTATE=" + viewState + "&__EVENTVALIDATION=" + eventValidation;
/*txt_title為標題內容,bookContent為內容txt_menuid為當前章節數cmdSaveConn.x=0&cmdSaveConn.y=0用於傳遞imagebutton控件傳遞參數 用於數據接收頁面的提交針對不同的按鈕用參數實現觸發祥見:http://hi.baidu.com/zeratul_bb/blog/item/34d9f7fda770c241d6887deb.html __VIEWSTATE和_EVENTVALIDATION是asp.net特有的隱藏值傳遞,目前認為作用在於傳遞數據~待查*/
// 將字符串轉換成字節數組
byte[] postData = Encoding.ASCII.GetBytes(postString);
// 上傳數據,返回頁面的字節數組
responseData = webClient.UploadData(uriString, "POST", postData); //本函數的核心,這里主要解決了用POST方法傳遞數據以模擬表單提交~還有就是避免了提交后返回到數據接收指定的頁面~是個很好的方法!!詳見:http://www.cnblogs.com/anjou/archive/2006/12/25/602943.html (asp.net中webClient填充和提交表單的方法!)
// 將返回的將字節數組轉換成字符串(HTML);
// ASP.NET 返回的頁面一般是Unicode,如果是簡體中文應使用
// Encoding.GetEncoding("GB2312").GetString(responseData)
srcString = Encoding.UTF8.GetString(responseData);
UpdateBook.UpdateXml(taskUrl, bookID, Ztagend);
return "成功添加數據,返回數據字節為:"+srcString.Length.ToString(); //向主調函數返回數據提交后轉到的頁面代碼長度!
///////////////////////////////////////
// 分析返回的頁面
///////////////////////////////////////
// ...... ......
}
#endregion
-----------------------------
根據不同按鈕總結如下:
Asp.net 中在客戶端觸發服務端事件分為兩種情況:
一. WebControls中的Button 和HtmlControls中的Type為submit的HtmlInputButton
這兩種按鈕最終到客戶端的表現形式為: <input name="Submit1" id="Submit1" type="submit" value=”Submit”>,這是Form表單的提交按鈕,點擊以后會作為參數發送到服務端,參數是這樣的: 控件的name屬性=控件的value值,對應上面的例子就是:Submit1= Submit。 服務端會根據接收到的控件的name屬性的這個key來得知是這個按鈕被點擊了,從而在服務端觸發這個按鈕的點擊事件。
二. ImageButton或者HttpInputImage:
這些控件到客戶端的表現類似這樣的: <input type=image id=img1>,點擊了這樣的控件會直接提交表單,作用同提交按鈕。點擊了這樣的控件傳到服務端的參數是這樣的:id.x=nn&id.y=nn,對應到上面的例子就是:img1.x=nn&img1.y=nn
三. HtmlControls 中的 Type為button的HtmlInputButton 和其它所有的控件事件,比如LinkButton點擊,TextBox的Change事件等等:
這些事件在客戶端產生后會經過一個統一的機制發送到服務端。
1. 首先asp.net頁框架會使用兩個Hidden域來存放表示是哪個控件觸發的事件,以及事件的參數:
<!—表示觸發事件的控件,一般是這個控件的name -->
<input type="hidden" name="__EVENTTARGET" value="" />
<!—表示觸發事件的參數,一般是當某個控件有兩個以上的事件時,用來區別是哪個事件 -->
<input type="hidden" name="__EVENTARGUMENT" value="" />
2. 服務端會生成一個jscript的方法來處理所有這些事件的發送,這段代碼是:
<script language="javascript">
<!--
function __doPostBack(eventTarget, eventArgument) {
var theform = document.WebForm2;
theform.__EVENTTARGET.value = eventTarget;
theform.__EVENTARGUMENT.value = eventArgument;
theform.submit();
}
// -->
</script>
3. 每個會引發服務端事件的控件都會在響應的客戶端事件中調用上面的代碼:
比如,HtmlControls 中的 Type為button的HtmlInputButton的點擊事件
<!—客戶端的點擊事件調用__doPostBack,eventTarget 參數為'Button2',表示是name為'Button2’控件觸發的事件,eventArgument 為空,表示這個Type為button的HtmlInputButton只有一個客戶端觸發的服務端事件-->
<input language="javascript" onclick="__doPostBack('Button2','')" name="Button2" id="Button2" type="button" value="Button" />
又比如,TextBox控件的Change事件
<!—客戶端的onchange事件調用__doPostBack,eventTarget 參數為’TextBox1’,表示是name為’TextBox1’控件觸發的事件,而TextBox控件只有一個客戶端觸發的服務端事件TextChanged,故服務器就會去觸發這個TextBox的TextChanged事件->
<input name="TextBox1" type="text" id="TextBox1" onchange="__doPostBack('TextBox1','')" language="javascript" />
4. 客戶端觸發事件后調用__doPostBack方法,將表示觸發的控件源的eventTarget 和事件參數eventArgument分別付給兩個隱藏域__EVENTTARGET和__EVENTARGUMENT,然后提交Form,在服務端根據__EVENTTARGET和__EVENTARGUMENT來判斷是哪個控件的什么事件觸發了。