Form(表單)對於每一個WEB開發人員來講,應該是再熟悉不過的東西了,可它倒是頁面與WEB服務器交互過程當中最重要的信息來源。 雖然Asp.net WebForms框架爲了幫助咱們簡化開發工做,作了很完美的封裝,讓咱們只須要簡單地使用服務端控件就能夠直接操做那些 HTML表單元素了。但我認爲了解一些基礎的東西,可使咱們沒必要束縛在WebForms框架上,以及遇到一些奇怪問題時, 能夠更從容地解決它們。javascript
今天,我將和你們來聊聊表單,這個簡單又基礎的東西。我將站在HTML和單純的Asp.net框架的角度來解釋它們的工做方式, 所以,本文不演示WebForms服務器控件的相關內容。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> </form>在這個HTML表單中,我定義了二個文本輸入框,一個提交按鈕,表單將提交到Handler1.ashx中處理,且以POST的方式。注意哦,若是咱們想讓純靜態頁面也能向服務器提交數據,就能夠採用這樣方式來處理:將action屬性指向一個服務器能處理的地址。說明:當咱們使用WebForms的服務器表單控件時,通常都會提交到頁面自身來處理(action屬性指向當前頁面), 這樣能夠方便地使用按鈕事件以及從服務器控件訪問從瀏覽器提交的控件輸入結果。
Form.Action = Request.RawUrl; // 受如下版本支持:3.5 SP一、3.0 SP一、2.0 SP1好了,咱們再回到前面那個HTML表單,看一下若是用戶點擊了「提交」按鈕,瀏覽器是如何把表單的內容發出的。 在此,咱們須要Fiddler工具的協助,請在提交表單前啓動好Fiddler。我將這個表單的提交請求過程作了以下截圖。
string name = context.Request.Form["CustomerName"]; string tel = context.Request.Form["CustomerTel"];代碼很簡單,直接根據表單控件的name屬性訪問Request.Form就能夠了。
<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> </form>服務端處理代碼
// 注意:咱們只要判斷指定的name是否存在就能夠了。 if( string.IsNullOrEmpty(context.Request.Form["btnSave"]) == false ) { // 保存的處理邏輯 } if( string.IsNullOrEmpty(context.Request.Form["btnQuery"]) == false ) { // 查詢的處理邏輯 }
<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> </form>
string action = context.Request.Form["submit"]; if( action == "保存" ) { // 保存的處理邏輯 } if( action == "查詢" ) { // 查詢的處理邏輯 }固然了,解決這個問題的方法不少,咱們還能夠在提交前修改form.action屬性。 對於MVC來講,可能有些人會選擇使用Filter的方式來處理。最終選擇哪一種方法,可根據各自喜愛來選擇。
<form action="Handler2.ashx" method="post" enctype="multipart/form-data"> <p><input type="text" name="str" value="一個字符串,別管它" /></p> <p>要上傳的文件1<input type="file" name="file1"/></p> <p>要上傳的文件2<input type="file" name="file2"/></p> <p><input type="submit" value="提交" /></p> </form>我將上傳2個小文件
HttpPostedFile file1 = context.Request.Files["file1"]; if( file1 != null && string.IsNullOrEmpty(file1.FileName) == false ) file1.SaveAs(context.Server.MapPath("~/App_Data/") + file1.FileName); HttpPostedFile file2 = context.Request.Files["file2"]; if( file2 != null && string.IsNullOrEmpty(file2.FileName) == false ) file2.SaveAs(context.Server.MapPath("~/App_Data/") + file2.FileName);或者
HttpFileCollection files = context.Request.Files; foreach( string key in files.AllKeys ) { HttpPostedFile file = files[key]; if( string.IsNullOrEmpty(file.FileName) == false ) file.SaveAs(context.Server.MapPath("~/App_Data/") + file.FileName); }二種方法都行,前者更能體現控件的name與服務端讀取的關係,後者在多文件上傳時有更好的擴展性。
<form action="/Home/Submit" method="post"> <p>客戶名稱: <input type="text" name="Name" style="width: 300px" /></p> <p>客戶電話: <input type="text" name="Tel" style="width: 300px" /></p> <p><input type="submit" value="提交" /></p> </form>Conntroller中的方法的簽名:
public ActionResult Submit(Customer customer) { } public ActionResult Submit(string name, string tel) { }以上二種方法都是能夠的,固然了,前者會比較好,但須要事先定義一個Customer類,代碼以下:
public class Customer { public string Name { get; set; } public string Tel { get; set; } }若是表單簡單或者業務邏輯簡單,咱們或許一直也不會遇到什麼麻煩,以上代碼能很好的工做。 可是,若是哪天咱們有了新的業務須要求,須要在這個表單中同時加上一些其它的內容,例如,要把業務員的資料也一塊兒錄入進去。 其中業務員的實體類定義以下:
public class Salesman { public string Name { get; set; } public string Tel { get; set; } }Controller的接口須要修改爲:
public ActionResult Submit(Customer customer, Salesman salesman) { }這時,HTML表單又該怎麼寫呢?恰好,這二個類的(部分)屬性名稱同樣,顯然,前面表單中的Name,Tel就沒法對應了。 此時咱們能夠將表單寫成以下形式:
<form action="/Home/Submit" method="post"> <p>客戶名稱: <input type="text" name="customer.Name" style="width: 300px" /></p> <p>客戶電話: <input type="text" name="customer.Tel" style="width: 300px" /></p> <p>銷售員名稱: <input type="text" name="salesman.Name" style="width: 300px" /></p> <p>銷售員電話: <input type="text" name="salesman.Tel" style="width: 300px" /></p> <p><input type="submit" value="提交" /></p> </form>注意Controller方法中的參數名與HTML表單中的name是有關係的。
<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> </form>JS代碼以下:
$(function(){ $('form').ajaxForm({ success: function(responseText){ alert(responseText); } }); });是的,就是這麼簡單,只要調用ajaxForm()就好了。你也能夠傳入任何$.ajax()能接受的參數。它的做用是:修改表單的提交方式,改爲Ajax方式提交。最終當用戶點擊「提交」按鈕時,此時再也不是瀏覽器的提交行爲了, 而是使用Ajax的方式提交,提交的URL以及提交方法就是在FORM中指定的參數。
$(function(){ $("#btnId").click(function(){ $('form').ajaxSubmit({ success: function(responseText){ alert(responseText); } }); }); });變化很小,只須要將ajaxForm修改爲ajaxSubmit就OK了。 與ajaxForm()不一樣,調用ajaxSubmit()方法將會當即提交表單。
<div id="divCustomerInfo"> <p>客戶名稱: <input type="text" name="CustomerName" style="width: 300px" /></p> <p>客戶電話: <input type="text" name="CustomerTel" style="width: 300px" /></p> </div>咱們能夠這樣來提交這部分表單的數據:
$("#btnId").click(function(){ $.ajax({ url: "Handler1.ashx", type: "POST", data: $('#divCustomerInfo :text').fieldSerialize(), success: function(responseText){ alert(responseText); } }); return false; });注意關鍵的代碼行:data: $('#divCustomerInfo :text').fieldSerialize()
$.ajax({ url: "Handler1.ashx", type: "POST", data: { id: 2, name: "aaa", tel: "~!@#$%^&*()_+-=<>?|", xxxx: "要多少還能夠寫多少", encoding: "見鬼去吧。?& :)" }, success: function(responseText) { $("#divResult").html(responseText); } });你說什麼,只能使用GET ? 哦,那就改一下 type 參數吧。
$.ajax({ url: "Handler1.ashx", type: "GET", data: { id: 2, name: "aaa", tel: "~!@#$%^&*()_+-=<>?|", xxxx: "要多少還能夠寫多少", encoding: "見鬼去吧。?& :)" }, success: function(responseText) { $("#divResult").html(responseText); } });看了這個示例,您還會繼續拼URL嗎?說明:爲了排版簡單,我將參數放在一行了,建議實際使用時,不要擠在一行。
/// <summary> /// 向指定的URL地址發起一個POST請求,同時能夠上傳一些數據項。 /// </summary> /// <param name="url">要請求的URL地址</param> /// <param name="keyvalues">要上傳的數據項</param> /// <param name="encoding">發送,接收的字符編碼方式</param> /// <returns>服務器的返回結果</returns> static string SendHttpRequestPost(string url, Dictionary<string, string> keyvalues, Encoding encoding) { if( string.IsNullOrEmpty(url) ) throw new ArgumentNullException("url"); string postData = null; // 將數據項轉變成 name1=value1&name2=value2 的形式 if( keyvalues != null && keyvalues.Count > 0 ) { postData = string.Join("&", (from kvp in keyvalues let item = kvp.Key + "=" + HttpUtility.UrlEncode(kvp.Value) select item ).ToArray() ); } if( encoding == null ) encoding = Encoding.UTF8; HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded; charset=" + encoding.WebName; if( postData != null ) { byte[] buffer = encoding.GetBytes(postData); Stream stream = request.GetRequestStream(); stream.Write(buffer, 0, buffer.Length); stream.Close(); } using( WebResponse response = request.GetResponse() ) { using( StreamReader reader = new StreamReader(response.GetResponseStream(), encoding) ) { return reader.ReadToEnd(); } } } // 調用上面方法的示例代碼 string Test_SendHttpRequestPost() { string url = "http://localhost:1272/FormWebSite1/Handler1.ashx"; Dictionary<string, string> keyvalues = new Dictionary<string, string>(); keyvalues.Add("CustomerName", "我是李奇峯,$%@+& ?#^/"); keyvalues.Add("CustomerTel", "1381723505x"); return SendHttpRequestPost(url, keyvalues, null); }
/// <summary> /// 向指定的URL地址發起一個POST請求,同時能夠上傳一些數據項以及上傳文件。 /// </summary> /// <param name="url">要請求的URL地址</param> /// <param name="keyvalues">要上傳的數據項</param> /// <param name="fileList">要上傳的文件列表</param> /// <param name="encoding">發送數據項,接收的字符編碼方式</param> /// <returns>服務器的返回結果</returns> static string SendHttpRequestPost(string url, Dictionary<string, string> keyvalues, Dictionary<string, string> fileList, Encoding encoding) { if( fileList == null ) return SendHttpRequestPost(url, keyvalues, encoding); if( string.IsNullOrEmpty(url) ) throw new ArgumentNullException("url"); if( encoding == null ) encoding = Encoding.UTF8; HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.Method = "POST"; // 要上傳文件,必定要是POST方法 // 數據塊的分隔標記,用於設置請求頭,注意:這個地方最好不要使用漢字。 string boundary = "---------------------------" + Guid.NewGuid().ToString("N"); // 數據塊的分隔標記,用於寫入請求體。 // 注意:前面多了一段: "--" ,並且它們將獨佔一行。 byte[] boundaryBytes = Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n"); // 設置請求頭。指示是一個上傳表單,以及各數據塊的分隔標記。 request.ContentType = "multipart/form-data; boundary=" + boundary; // 先獲得請求流,準備寫入數據。 Stream stream = request.GetRequestStream(); if( keyvalues != null && keyvalues.Count > 0 ) { // 寫入非文件的keyvalues部分 foreach( KeyValuePair<string, string> kvp in keyvalues ) { // 寫入數據塊的分隔標記 stream.Write(boundaryBytes, 0, boundaryBytes.Length); // 寫入數據項描述,這裏的Value部分能夠不用URL編碼 string str = string.Format( "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}", kvp.Key, kvp.Value); byte[] data = encoding.GetBytes(str); stream.Write(data, 0, data.Length); } } // 寫入要上傳的文件 foreach( KeyValuePair<string, string> kvp in fileList ) { // 寫入數據塊的分隔標記 stream.Write(boundaryBytes, 0, boundaryBytes.Length); // 寫入文件描述,這裏設置一個通用的類型描述:application/octet-stream,具體的描述在註冊表裏有。 string description = string.Format( "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n" + "Content-Type: application/octet-stream\r\n\r\n", kvp.Key, Path.GetFileName(kvp.Value)); // 注意:這裏若是不使用UTF-8,對於漢字會有亂碼。 byte[] header = Encoding.UTF8.GetBytes(description); stream.Write(header, 0, header.Length); // 寫入文件內容 byte[] body = File.ReadAllBytes(kvp.Value); stream.Write(body, 0, body.Length); } // 寫入結束標記 boundaryBytes = Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n"); stream.Write(boundaryBytes, 0, boundaryBytes.Length); stream.Close(); // 開始發起請求,並獲取服務器返回的結果。 using( WebResponse response = request.GetResponse() ) { using( StreamReader reader = new StreamReader(response.GetResponseStream(), encoding) ) { return reader.ReadToEnd(); } } } // 調用上面方法的示例代碼 string Test_SendHttpRequestPost2() { string url = "http://localhost:1272/FormWebSite1/Handler2.ashx"; Dictionary<string, string> keyvalues = new Dictionary<string, string>(); keyvalues.Add("Key1", "本示例代碼由 Fish Li 提供"); keyvalues.Add("Key2", "http://www.cnblogs.com/fish-li"); keyvalues.Add("Key3", "來幾個特殊字符:~!@#$%^&*()-=_+{}[]:;'\"<>?/.,|\\"); Dictionary<string, string> fileList = new Dictionary<string, string>(); fileList.Add("file1", @"H:\AllTempFiles\ascx中文字.gif"); fileList.Add("file2", @"H:\AllTempFiles\asax中文字.gif"); return SendHttpRequestPost(url, keyvalues, fileList, Encoding.UTF8); }