前面一直在说”浏览器提交表单",事实上我们也可以用javascript提交表单,好处也有很多,比如前面所说的F5刷新问题。 以Ajax方式提交表单的更大好处它是异步的,还可以实现局部刷新,这些特性都是浏览器提交方式没有的。 前面我提到表单在提交时,浏览器要实现的4个步骤,基本上用JS来完成这个操作也是一样的。 但是,前面说的步骤好像很麻烦呢,有没有简单的方法来实现这个过程呢? 嗯,有的,这里我将使用jquery以及jquery.form.js这个插件来演示这个复杂过程的简单处理方案。
示例用的HTML表单还是我前面用的代码,完全不需要修改:
JS代码如下:
是的,就是这么简单,只要调用ajaxForm()就行了。你也可以传入任何$.ajax()能接受的参数。
它的作用是:修改表单的提交方式,改成Ajax方式提交。最终当用户点击“提交”按钮时,此时不再是浏览器的提交行为了, 而是使用Ajax的方式提交,提交的URL以及提交方法就是在FORM中指定的参数。
如果您希望要用户点击某个按钮或者链接时,也能提交表单(不经过提交按钮),那么可以使用如下方法:
变化很小,只需要将ajaxForm修改成ajaxSubmit就OK了。 与ajaxForm()不同,调用ajaxSubmit()方法将会立即提交表单。
回到顶部
以Ajax方式提交部分表单
在前面的示例中,我们看到以Ajax方式提交一个表单是非常容易的,它完全模拟了浏览器的行为。 不过,有时我们可能需要只提交表单的一部分,为的是更好的局部更新,那么又该如何做呢?
假如我有以下表单的一部分,我只希望在用户某个按钮时将它提交到服务端:
我们可以这样来提交这部分表单的数据:
注意关键的代码行:data: $('#divCustomerInfo :text').fieldSerialize()
注意:此时将由您指定一个【jquery选择器】来过滤要提交的控件,而不是使用成功控件的筛选逻辑。
或者,您也可以使用下面将要介绍的方法,仍然是使用 data: {} 的方式,但需要手工指定数据成员。
回到顶部
使用JQuery,就不要再拼URL了!
JQuery越来越流行,以至于在创建MVC项目时,VS IDE会把JQuery也准备好了,可能MS认为开发WEB项目离不开JQuery了。
的确,JQuery非常方便,尤其是在处理DOM时,不仅如此,在处理AJAX请求时,也非常方便。
不过,有件事却让我很纳闷:经常看到有人在使用JQuery实现Ajax时,把一堆参数放在URL中传递,当然了, 发送GET请求嘛,这样做不错,但是,让我不解的是:URL是拼接起来的,而且代码又臭又长!
如果是一个简单的参数:"aaa.aspx?id=" + xxId ,这样也就罢了。但是当一堆参数拼接在一起时,可能一下子还看不清楚到底有几个什么样的参数。 而且经验丰富一些的开发人员会发现这样做有时会有乱码问题,可能网上搜过后,知道还有编码的工作要处理,于是又加了一堆编码方法。 到此为止,这段代码会让人看起来很累!
如果您平时也是这样做的,那么我今天就告诉您:不要再拼接URL了! $.ajax()的参数不是有个data成员嘛,用它吧。看代码:
你说什么,只能使用GET ? 哦,那就改一下 type 参数吧。
看了这个示例,您还会继续拼URL吗?
说明:为了排版简单,我将参数放在一行了,建议实际使用时,不要挤在一行。
回到顶部
id, name 有什么关系
通常我们在写HTML代码时,会给控件指定一个id属性,这个属性只供JS和CSS使用,在表单提交时,它不起任何作用。
在上面的示例代码中,可能data {}中的各个value就来源于各个不同的控件,那么为那些控件指定相应的id属性将会方便地找到它们。
但是如果不需要用JS和CSS控制的控件,或许它们只是用来显示一些数据(只读),那么就没有必要指定id属性, 当然了,name属性也可以不用给出(避免提交无意义的数据)。
回到顶部
使用C#模拟浏览器提交表单
浏览器也是一个普通的应用程序,.net framework也提供一些类也能让我们直接发起HTTP请求。 今天我将再次用C#来模拟浏览器的提交请求,同时也可以加深对HTTP请求的理解。
示例代码分为二段,一段示范了使用application/x-www-form-urlencoded编码方式提交, 另一段则示范了使用multipart/form-data的编码方式。
为了让大家能再次利用这些代码,我已将关键部分写成独立方法,希望当您有这方面的需求时能马上可以用上。 代码如下:
1. application/x-www-form-urlencoded
/// <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);
}
2. multipart/form-data 。注意这部分代码有点复杂,因此我加了很多注释。
/// <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("rn--" + boundary + "rn");
// 设置请求头。指示是一个上传表单,以及各数据块的分隔标记。
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}"rnrn{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}"rn" +
"Content-Type: application/octet-streamrnrn",
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("rn--" + boundary + "--rn");
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:AllTempFilesascx中文字.gif");
fileList.Add("file2", @"H:AllTempFilesasax中文字.gif");
return SendHttpRequestPost(url, keyvalues, fileList, Encoding.UTF8);
}
说明:上面的示例方法中,我并没有对KEY编码,是因为:我想大家选用的KEY应该是不需要编码的(英文字母与数字的组合)。
而且,我也没加入对Cookie处理的那部分代码,如果您需要在发送请求时,保留Cookie,那么请参考我上一篇博客 【细说Cookie】中的示例代码。
原文链接:http://www.cnblogs.com/fish-li/archive/2011/07/17/2108884.html