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); }