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 == "查询") { // 查询的处理逻辑 }