sailing

Everything...

使用HttpWebRequest发送自定义POST请求



范例代码下载
平时用浏览器看网页的时候,点击一下submit按钮的时候其实就是给服务器发送了一个POST请求。但是如何在自己的C#程序里面实现类似的功能呢?本文给出了一个简单的范例,可以实现类似的和web server之间的POST通讯。通过程序发送POST的过程如下所示:
1. 创建httpWebRequest对象
HttpWebRequest不能直接通过new来创建,只能通过WebRequest.Create(url)的方式来获得。
WebRequest是获得一些列应用层协议对象的一个统一的入口(工厂模式),它根据参数的协议来确定最终创建的对象类型。所以我们的程序里面有一个对返回对象的类型进行测试的过程。
2. 初始化HttpWebRequest对象
这个过程提供一些http请求常用的属性:agentstring,contenttype等其中agentstring比较有意思,它是用来识别你用的浏览器名字的,通过设置这个属性你可以欺骗服务器你是一个IE,firefox甚至是mac里面的safari。很多认真设计的网站都会根据这个值来返回对用户浏览器特别优化过的代码。
3. 附加要POST给服务器的数据到HttpWebRequest对象
附加POST数据的过程比较特殊,它并没有提供一个属性给用户存取,需要写入HttpWebRequest对象提供的一个stream里面。
4. 读取服务器的返回信息
读取服务器返回的时候,要注意返回数据的encoding。如果我们提供的解码类型不对会造成乱码。比较常见的是utf-8和gb2312之间的混淆,据我测试,国内的主机一般都是gb2312编码的。一般设计良好的网站会把它编码的方式放在返回的http header里面,但是也有不少网站根本没有,我们只能通过一个对返回二进制值的统计方法来确定它的编码方式。

 

using System;

using System.Collections.Generic;

using System.Text;

using System.Net;

using System.IO;

 

namespace SimpleWebRequest

{

    class Program

    {

        static void Main(string[] args)

        {

            Console.WriteLine(

                PostDataToUrl("test", "http://www.microsoft.com")

                );

        }

 

        /// <summary>

        /// Post dataurl

        /// </summary>

        /// <param name="data">post的数据</param>

        /// <param name="url">目标url</param>

        /// <returns>服务器响应</returns>

        static string PostDataToUrl(string data, string url)

        {

            Encoding encoding = Encoding.GetEncoding(sRequestEncoding);

            byte[] bytesToPost = encoding.GetBytes(data);

            return PostDataToUrl(bytesToPost, url);

        }

 

        /// <summary>

        /// Post dataurl

        /// </summary>

        /// <param name="data">post的数据</param>

        /// <param name="url">目标url</param>

        /// <returns>服务器响应</returns>

        static string PostDataToUrl(byte[] data, string url)

        {

            #region 创建httpWebRequest对象

            WebRequest webRequest = WebRequest.Create(url);

            HttpWebRequest httpRequest = webRequest as HttpWebRequest;

            if (httpRequest == null)

            {

                throw new ApplicationException(

                    string.Format("Invalid url string: {0}", url)

                    );

            }

            #endregion

 

            #region 填充httpWebRequest的基本信息

            httpRequest.UserAgent = sUserAgent;

            httpRequest.ContentType = sContentType;

            httpRequest.Method = "POST";

            #endregion

 

            #region 填充要post的内容

            httpRequest.ContentLength = data.Length;

            Stream requestStream = httpRequest.GetRequestStream();

            requestStream.Write(data, 0, data.Length);

            requestStream.Close();

            #endregion

 

            #region 发送post请求到服务器并读取服务器返回信息

            Stream responseStream;

            try

            {

                responseStream = httpRequest.GetResponse().GetResponseStream();

            }

            catch(Exception e)

            {

                // log error

                Console.WriteLine(

                    string.Format("POST操作发生异常:{0}", e.Message)

                    );

                throw e;

            }

            #endregion

 

            #region 读取服务器返回信息

            string stringResponse = string.Empty;

            using(StreamReader responseReader =

                new StreamReader(responseStream, Encoding.GetEncoding(sResponseEncoding)))

            {

                stringResponse = responseReader.ReadToEnd();

            }

            responseStream.Close();

            #endregion

            return stringResponse;

        }

 

        const string sUserAgent =

            "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727)";

        const string sContentType =

            "application/x-www-form-urlencoded";

        const string sRequestEncoding = "ascii";

        const string sResponseEncoding = "gb2312";

    }

}

 

posted on 2007-09-03 01:09 乌生鱼汤 阅读(2842) 评论(15)  编辑 收藏

评论

#1楼  2007-09-04 04:30 wtw [未注册用户]

感谢踏雪,帮我解决了一个一直没有弄明白的问题   回复  引用    

#2楼  2007-09-04 10:11 Clark Zheng      

讲得太简单,最起码连最重要的cookie没有保持下来,那么紧接着的下一次请求估计很多情况下不能获取希望得到的信息   回复  引用  查看    

#3楼 [楼主] 2007-09-04 14:50 踏雪无痕      

这是最基本的实现方式,在此基础上可以加入其它的功能。如果需要加cookie,可以加到代码的第二个region:对httpWebRequest对象的初始化里面。   回复  引用  查看    

#4楼  2007-09-18 11:45 访客 [未注册用户]

我在发提交数据里的里面带有:<a href=http://www.baidu.com>a</a>提交后,显示的只有:a
  回复  引用    

#5楼 [楼主] 2007-09-18 18:49 踏雪无痕      

@访客
提交之前你要先urlencode的。   回复  引用  查看    

#6楼  2007-09-25 11:13 base [未注册用户]

这方法不行啊。新建一个简单的页面,页面上有2个Textbox,添加的数据用静态ArrayList保存,Page_Load时显示添加的数据。

用的类添加不上,你试试。   回复  引用    

#7楼 [楼主] 2007-09-25 20:01 踏雪无痕      

楼上的,我和你说的不是同一个东西好不好。   回复  引用  查看    

#8楼  2007-09-26 00:21 base [未注册用户]

前面我没说清楚,我的意思是用你的类POST数据不成功。

我做了一个简单的页面用来做测试,页面上有2个Textbox,添加后的数据用静态ArrayList保存,Page_Load时显示ArrayList的数据。

如果用HttpWebRequest POST过去的数据添加上了,在测试的页面打开的时候添加的数据应该被显示出来,现在问题是没有显示。

刚才看到一种新的说法,说.net2.0中需要把VIEWSTATE中的数据一起POST回去,添加上VIEWSTATE还是不行。

你的这段代码你用过没有?你能不能也向我上面说的那样做个简单的页面测试一下看有没有问题,我在网上看到的POST数据的代码都跟你的大同小异,但都不行,奇怪了!!   回复  引用    

#9楼 [楼主] 2007-09-26 01:14 踏雪无痕      

看看你出什么错了啊?把你的错误信息发给我啊。
没事干嘛要去折腾asp.net的post啊,它还有一个eventvalidation的,包括viewstate一个都不能少,而且encoding都要对啊,包括url encode和字符的encoding gb2312,utf-8之类。另外,要把cookie放上去,如果有的话,一个都不能少的。我的这个是讲如何发post的方法,不涉及特定服务器期待什么数据,你要准备什么数据。   回复  引用  查看    

#10楼  2007-09-26 17:35 base [未注册用户]

没有什么错误信息,PostDataToUrl方法也可以收到服务器的Response。
像我前面的那个简单的用来测试你的类的例子,POST出去的数据服务器应该没有处理这部分,因为PostDataToUrl方法的data参数有没有数据收到Response都一样,如果服务器处理了这些数据应该在下一次Page_Load的时候将这些数据添加上去。
像你说的服务器需要eventvalidation、encoding,一般哪些情况服务器需要这些,向tomcat的jsp POST数据的时候是否也需要eventvalidation、encoding。eventvalidation的数据也是添加在data参数里面?HttpWebRequest的URL好像不能修改,如果我要接收其他URL Response的数据只能再新建一个HttpWebRequest?
能不能做个对应的例子来说明你的类在这种情况下是如何工作的,也就是增加一个WebServer的例子,再修改一下你的这个类做个WebClient,然后WebClient POST数据到WebServer   回复  引用    

#11楼 [楼主] 2007-09-27 04:12 踏雪无痕      

你要post到哪里啊?
asp.net和jsp又是不一样的,不过只要你数据做得对,我这个只是一个POST工具,应该没什么影响。不过,我还是有点相信用HttpWebRequest发的数据会自动带上些垃圾。可以用TcpClient试试发送全部自己写的包。   回复  引用  查看    

#12楼  2007-09-27 22:19 base [未注册用户]

随便POST到那个页面都可以,只是想做个例子证实一下而已。
TcpClient没用过HTTP协议不太懂,没法写:(   回复  引用    

#13楼  2008-05-14 15:24 steven love sunny      

急!我想问下如果说是某网站的某个网页接收这段Post的数据流(比方说我将一个文件转换为byte流放入request流中),如何将其在页面接收并还原这段数据信息。
  回复  引用  查看    

#14楼 [楼主] 2008-05-16 09:07 乌生鱼汤      

这个是发附件了,有些难度,你要生成类似下面的请求。不过可以用webclient来做,它封装好了,你不用自己写,缺点是webclient得灵活度小。


POST /test/Default2.aspx HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/msword, application/vnd.ms-excel, */*
Referer: http://localhost/test/Default2.aspx
Accept-Language: en-us
Content-Type: multipart/form-data; boundary=---------------------------7d8242d410280
UA-CPU: x86
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)
Host: localhost
Content-Length: 453
Connection: Keep-Alive
Cache-Control: no-cache

-----------------------------7d8242d410280
Content-Disposition: form-data; name="FileUpload1"; filename="test.htm"
Content-Type: text/plain

<html>
<form actu>
</form>
</html>
-----------------------------7d8242d410280--
  回复  引用  查看    

#15楼  2008-05-29 15:40 Vincent Love      

int resault = 0;
HttpWebResponse httpresponse=null;
string url = "http://www.g123gagdagsarte4523.com";
string number = "123465789";
string statuscode = "hello";
int PostBackStatus = 0;
string postData = "Number=" + number + "&" + "Status=" + statuscode;

//要post的数据
Encoding encoding = Encoding.Default;
byte[] bytesPostData = encoding.GetBytes(postData);

try
{
//创建httpWebRequest对象
HttpWebRequest httprequest = (HttpWebRequest)WebRequest.Create(url);
if (httprequest == null)
{
throw new ApplicationException(string.Format("Invalid Url string :{0}", url));
}

//填充httpWebRequest的基本信息
httprequest.UserAgent = "Mozilla/4.0";
httprequest.ContentType = "application/x-www-form-urlencoded";
httprequest.Method = "POST";

//填充要post的内容
httprequest.ContentLength = bytesPostData.Length;
Stream requestStream = httprequest.GetRequestStream();
requestStream.Write(bytesPostData, 0, bytesPostData.Length);
requestStream.Close();

//发送post请求到服务器并读取服务器返回信息
httpresponse = (HttpWebResponse)httprequest.GetResponse();
if (httpresponse.StatusCode == HttpStatusCode.OK)
{
PostBackStatus = Convert.ToInt32(httpresponse.StatusCode);
}
}
catch (WebException ex)
{
PostBackStatus = Convert.ToInt32(ex.Status);
}
catch (HttpListenerException ex)
{
PostBackStatus = Convert.ToInt32(ex.ErrorCode);
}
为什么我返回的PostBackStatus =200,但是URL地址不存在,为什么?   回复  引用  查看    


标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2007-09-03 18:32 编辑过
 
另存  打印
 

导航

统计

与我联系

我的标签

随笔档案(165)

Asp

Friends

其它链接

最新评论

阅读排行榜

60天内阅读排行