学习本篇之前,对 HttpWebRequest 与 HttpWebResponse 不太熟悉的同学,请先学习《C# HTTP系列》。

应用程序中使用HTTP协议和服务器交互主要是进行数据的上传与下载,最常见的方式是通过 GET 和 POST 两种方式来完成。本篇介绍 C# HttpWebRequest 如何使用这两种方式来实现。

示例场景:

 <form id="form1" runat="server" action="UserManageHandler.ashx" method="post" enctype="application/x-www-form-urlencoded">
<div>
名称: <input type="text" name="uname" class="uname" /><br />
邮件: <input type="text" name="email" class="email" /><br />
<input type="submit" name="submit" value="提交" />
</div>
</form>

 using System;
using System.Web; namespace SparkSoft.Platform.UI.WebForm.Test
{
public class UserManageHandler : IHttpHandler
{ public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain"; string uname = context.Request["uname"];
string email = context.Request["email"]; context.Response.Write("提交结果如下:" + Environment.NewLine +
"名称:" + uname + Environment.NewLine +
"邮箱:" + email);
} public bool IsReusable
{
get { return false; }
}
}
}
01 HttpWebRequest 提交数据方式1 GET方式
GET 方式通过在网络地址附加参数来完成数据的提交,
比如在地址 http://localhost:5000/Test/UserManageHandler.ashx?uname=zhangsan 中,前面部分 http://localhost:5000/Test/UserManageHandler.ashx 表示数据提交的网址,后面部分 uname=zhangsan 表示附加的参数,其中uname 表示一个键(key), zhangsan 表示这个键对应的值(value)。程序代码如下:
 /// <summary>
/// 普通 GET 方式请求
/// </summary>
public void Request01_ByGet()
{
HttpWebRequest httpWebRequest = WebRequest.Create("http://localhost:5000/Test/UserManageHandler.ashx?uname=zhangsan") as HttpWebRequest;
httpWebRequest.Method = "GET"; HttpWebResponse httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse; // 获取响应
if (httpWebResponse != null)
{
using (StreamReader sr = new StreamReader(httpWebResponse.GetResponseStream()))
{
string content = sr.ReadToEnd();
} httpWebResponse.Close();
}
}
02 HttpWebRequest 提交数据方式2 POST方式
POST 方式通过在页面内容中填写参数的方法来完成数据的提交,

参数的格式和 GET 方式一样,是类似于 uname=zhangsan&email=123456@qq.com 这样的结构。程序代码如下:

 /// <summary>
/// 普通 POST 方式请求
/// </summary>
public void Request02_ByPost()
{
string param = "uname=zhangsan&email=123456@qq.com"; //参数
byte[] paramBytes = Encoding.ASCII.GetBytes(param); //参数转化为 ASCII 码 HttpWebRequest httpWebRequest = WebRequest.Create("http://localhost:5000/Test/UserManageHandler.ashx") as HttpWebRequest;
httpWebRequest.Method = "POST";
httpWebRequest.ContentType = "application/x-www-form-urlencoded";
httpWebRequest.ContentLength = paramBytes.Length; using (Stream reqStream = httpWebRequest.GetRequestStream())
{
reqStream.Write(paramBytes, , paramBytes.Length);
} HttpWebResponse httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse; // 获取响应
if (httpWebResponse != null)
{
using (StreamReader sr = new StreamReader(httpWebResponse.GetResponseStream()))
{
string content = sr.ReadToEnd();
} httpWebResponse.Close();
}
}

如果提交的请求参数中包含中文,那么需要对其进行编码,让目标网站能够识别。

03 HttpWebRequest 提交数据方式3 GET方式提交中文数据
GET 方式通过在网络地址中附加参数来完成数据提交,对于中文的编码,常用的有 gb2312 和 utf-8 两种。下面以 gb2312 方式编码来说明,程序代码如下:
 /// <summary>
/// 使用 GET 方式提交中文数据
/// </summary>
public void Request03_ByGet()
{
/*GET 方式通过在网络地址中附加参数来完成数据提交,对于中文的编码,常用的有 gb2312 和 utf8 两种。
* 由于无法告知对方提交数据的编码类型,所以编码方式要以对方的网站为标准。
* 常见的网站中, www.baidu.com (百度)的编码方式是 gb2312, www.google.com (谷歌)的编码方式是 utf8。
*/
Encoding myEncoding = Encoding.GetEncoding("gb2312"); //确定用哪种中文编码方式
string address = "http://www.baidu.com/s?" + HttpUtility.UrlEncode("参数一", myEncoding) + "=" + HttpUtility.UrlEncode("值一", myEncoding); //拼接数据提交的网址和经过中文编码后的中文参数 HttpWebRequest httpWebRequest = WebRequest.Create(address) as HttpWebRequest;
httpWebRequest.Method = "GET"; HttpWebResponse httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse; // 获取响应
if (httpWebResponse != null)
{
using (StreamReader sr = new StreamReader(httpWebResponse.GetResponseStream()))
{
string content = sr.ReadToEnd();
} httpWebResponse.Close();
}
}

在上面的程序代码中,我们以 GET 方式访问了网址 http://www.baidu.com/s ,传递了参数“参数一=值一”,由于无法告知对方提交数据的编码类型,所以编码方式要以对方的网站为标准。常见的网站中, www.baidu.com (百度)的编码方式是 gb2312, www.google.com (谷歌)的编码方式是 utf-8。

04 HttpWebRequest 提交数据方式4 POST方式提交中文数据
POST 方式通过在页面内容中填写参数的方法来完成数据的提交,由于提交的参数中可以说明使用的编码方式,所以理论上能获得更大的兼容性。下面以 gb2312 方式编码来说明,程序代码如下:
/// <summary>
/// 使用 POST 方式提交中文数据
/// </summary>
public void Request04_ByPost()
{
/* POST 方式通过在页面内容中填写参数的方法来完成数据的提交,由于提交的参数中可以说明使用的编码方式,所以理论上能获得更大的兼容性。*/ Encoding myEncoding = Encoding.GetEncoding("gb2312"); //确定用哪种中文编码方式
string param = HttpUtility.UrlEncode("参数一", myEncoding) + "=" + HttpUtility.UrlEncode("值一", myEncoding) + "&"
+ HttpUtility.UrlEncode("参数二", myEncoding) + "=" + HttpUtility.UrlEncode("值二", myEncoding);
byte[] paramBytes = Encoding.ASCII.GetBytes(param); //参数转化为 ASCII 码 HttpWebRequest httpWebRequest = WebRequest.Create("https://www.baidu.com/") as HttpWebRequest;
httpWebRequest.Method = "POST";
httpWebRequest.ContentType = "application/x-www-form-urlencoded;charset=gb2312";
httpWebRequest.ContentLength = paramBytes.Length; using (Stream reqStream = httpWebRequest.GetRequestStream())
{
reqStream.Write(paramBytes, , paramBytes.Length);
} HttpWebResponse httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse; // 获取响应
if (httpWebResponse != null)
{
using (StreamReader sr = new StreamReader(httpWebResponse.GetResponseStream()))
{
string content = sr.ReadToEnd();
} httpWebResponse.Close();
}
}

以上列出了客户端程序使用HTTP协议与服务器交互的情况,常用的是 GET 和 POST 方式。现在流行的 WebService 也是通过 HTTP 协议来交互的,使用的是 POST 方法。与以上稍有所不同的是, WebService 提交的数据内容和接收到的数据内容都是使用了 XML 方式编码。所以, HttpWebRequest 也可以使用在调用 WebService 的场景下。

HttpWebRequest 请求通用方法
(不包含body数据)POST、GET请求
 /// <summary>
/// HTTP-GET方法,(不包含body数据)。
/// 发送 HTTP 请求并返回来自 Internet 资源的响应(HTML代码)
/// </summary>
/// <param name="url">请求目标URL</param>
/// <returns>HTTP-GET的响应结果</returns>
public HttpResult Get(string url)
{
return Request(url, WebRequestMethods.Http.Get);
}
 /// <summary>
/// HTTP-POST方法,(不包含body数据)。
/// 发送 HTTP 请求并返回来自 Internet 资源的响应(HTML代码)
/// </summary>
/// <param name="url">请求目标URL</param>
/// <returns>HTTP-POST的响应结果</returns>
public HttpResult Post(string url)
{
return Request(url, WebRequestMethods.Http.Post);
}

(包含文本的body数据)请求

 /// <summary>
/// HTTP请求(包含JSON文本的body数据)
/// </summary>
/// <param name="url">请求目标URL</param>
/// <param name="data">主体数据(JSON文本)。如果参数中有中文,请使用合适的编码方式进行编码,例如:gb2312或者utf-8</param>
/// <param name="method">请求的方法。请使用 WebRequestMethods.Http 的枚举值</param>
/// <returns></returns>
public HttpResult UploadJson(string url, string data, string method = WebRequestMethods.Http.Post)
{
return Request(url, data, method, HttpContentType.APPLICATION_JSON);
}
 /// <summary>
/// HTTP请求(包含普通文本的body数据)
/// </summary>
/// <param name="url">请求目标URL</param>
/// <param name="data">主体数据(普通文本)。如果参数中有中文,请使用合适的编码方式进行编码,例如:gb2312或者utf-8</param>
/// <param name="method">请求的方法。请使用 WebRequestMethods.Http 的枚举值</param>
/// <returns></returns>
public HttpResult UploadText(string url, string data, string method = WebRequestMethods.Http.Post)
{
return Request(url, data, method, HttpContentType.TEXT_PLAIN);
}

上面的4个方法调用了公用的业务方法,分别如下:

 /// <summary>
/// HTTP请求,(不包含body数据)。
/// 发送 HTTP 请求并返回来自 Internet 资源的响应(HTML代码)
/// </summary>
/// <param name="url">请求目标URL</param>
/// <param name="method">请求的方法。请使用 WebRequestMethods.Http 的枚举值</param>
/// <returns>HTTP的响应结果</returns>
private HttpResult Request(string url, string method)
{
HttpResult httpResult = new HttpResult();
HttpWebRequest httpWebRequest = null;
try
{
httpWebRequest = WebRequest.Create(url) as HttpWebRequest;
httpWebRequest.Method = method;
httpWebRequest.UserAgent = _userAgent;
httpWebRequest.AllowAutoRedirect = _allowAutoRedirect;
httpWebRequest.ServicePoint.Expect100Continue = false; HttpWebResponse httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse;
if (httpWebResponse != null)
{
GetResponse(ref httpResult, httpWebResponse);
httpWebResponse.Close();
}
}
catch (WebException webException)
{
GetWebExceptionResponse(ref httpResult, webException);
}
catch (Exception ex)
{
GetExceptionResponse(ref httpResult, ex, method, string.Empty);
}
finally
{
if (httpWebRequest != null)
{
httpWebRequest.Abort();
}
} return httpResult;
}
 /// <summary>
/// HTTP请求(包含文本的body数据)
/// </summary>
/// <param name="url">请求目标URL</param>
/// <param name="data">主体数据(普通文本或者JSON文本)。如果参数中有中文,请使用合适的编码方式进行编码,例如:gb2312或者utf-8</param>
/// <param name="method">请求的方法。请使用 WebRequestMethods.Http 的枚举值</param>
/// <param name="contentType"><see langword="Content-type" /> HTTP 标头的值。请使用 ContentType 类的常量来获取</param>
/// <returns></returns>
private HttpResult Request(string url, string data, string method, string contentType)
{
HttpResult httpResult = new HttpResult();
HttpWebRequest httpWebRequest = null; try
{
httpWebRequest = WebRequest.Create(url) as HttpWebRequest;
httpWebRequest.Method = method;
httpWebRequest.Headers = HeaderCollection;
httpWebRequest.CookieContainer = CookieContainer;
httpWebRequest.ContentType = contentType;// 此属性的值存储在WebHeaderCollection中。如果设置了WebHeaderCollection,则属性值将丢失。所以放置在Headers 属性之后设置
httpWebRequest.UserAgent = _userAgent;
httpWebRequest.AllowAutoRedirect = _allowAutoRedirect;
httpWebRequest.ServicePoint.Expect100Continue = false; if (data != null)
{
httpWebRequest.AllowWriteStreamBuffering = true;
using (Stream requestStream = httpWebRequest.GetRequestStream())
{
requestStream.Write(EncodingType.GetBytes(data), , data.Length);//将请求参数写入请求流中
requestStream.Flush();
}
} HttpWebResponse httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse;
if (httpWebResponse != null)
{
GetResponse(ref httpResult, httpWebResponse);
httpWebResponse.Close();
}
}
catch (WebException webException)
{
GetWebExceptionResponse(ref httpResult, webException);
}
catch (Exception ex)
{
GetExceptionResponse(ref httpResult, ex, method, contentType);
}
finally
{
if (httpWebRequest != null)
{
httpWebRequest.Abort();
}
} return httpResult;
}

其中2个Request方法中用到了其他的封装类,比如:HttpResult

 /// <summary>
/// HTTP请求(GET,POST等)的响应返回消息
/// </summary>
public sealed class HttpResult
{
#region 字段 /// <summary>
/// HTTP 响应成功,即状态码为200
/// </summary>
public const string STATUS_SUCCESS = "success"; /// <summary>
/// HTTP 响应失败
/// </summary>
public const string STATUS_FAIL = "fail"; #endregion #region 属性 /// <summary>
/// 获取或设置请求的响应状态,success 或者 fail。建议使用常量:HttpResult.STATUS_SUCCESS 与 HttpResult.STATUS_FAIL
/// </summary>
public string Status { get; set; } /// <summary>
/// 获取或设置请求的响应状态描述
/// </summary>
public string StatusDescription { get; set; } /// <summary>
/// 状态码。与 HttpWebResponse.StatusCode 完全相同
/// </summary>
public int? StatusCode { get; set; } /// <summary>
/// 响应消息或错误文本
/// </summary>
public string Text { get; set; } /// <summary>
/// 响应消息或错误(二进制格式)
/// </summary>
public byte[] Data { get; set; } /// <summary>
/// 参考代码(用户自定义)。
/// 当 Status 等于 success 时,该值为 null;
/// 当 Status 等于 fail 时,该值为程序给出的用户自定义编码。
/// </summary>
public int? RefCode { get; set; } /// <summary>
/// 附加信息(用户自定义内容,如Exception内容或者自定义提示信息)。
/// 当 Status 等于 success 时,该值为为空
/// 当 Status 等于 fail 时,该值为程序给出的用户自定义内容,如Exception内容或者自定义提示信息。
/// </summary>
public string RefText { get; set; } /// <summary>
/// 获取或设置Http的请求响应。
/// </summary>
public HttpWebResponse HttpWebResponse { get; set; } ///// <summary>
///// 参考信息(从返回消息 WebResponse 的头部获取)
///// </summary>
//public Dictionary<string, string> RefInfo { get; set; } #endregion #region 构造函数
/// <summary>
/// 初始化(所有成员默认值,需要后续赋值)
/// </summary>
public HttpResult()
{
Status = string.Empty;
StatusDescription = string.Empty;
StatusCode = null;
Text = string.Empty;
Data = null; RefCode = null;
RefText = string.Empty;
//RefInfo = null; HttpWebResponse = null;
} #endregion #region 方法 /// <summary>
/// 对象复制
/// </summary>
/// <param name="httpResultSource">要复制其内容的来源</param>
public void Shadow(HttpResult httpResultSource)
{
this.Status = httpResultSource.Status;
this.StatusDescription = string.Empty;
this.StatusCode = httpResultSource.StatusCode;
this.Text = httpResultSource.Text;
this.Data = httpResultSource.Data; this.RefCode = httpResultSource.RefCode;
this.RefText += httpResultSource.RefText;
//this.RefInfo = httpResultSource.RefInfo; this.HttpWebResponse = httpResultSource.HttpWebResponse;
} /// <summary>
/// 转换为易读或便于打印的字符串格式
/// </summary>
/// <returns>便于打印和阅读的字符串</returns>
public override string ToString()
{
StringBuilder sb = new StringBuilder(); sb.AppendFormat("Status:{0}", Status);
sb.AppendFormat("StatusCode:{0}", StatusCode);
sb.AppendFormat("StatusDescription:{0}", StatusDescription);
sb.AppendLine(); if (!string.IsNullOrEmpty(Text))
{
sb.AppendLine("text:");
sb.AppendLine(Text);
} if (Data != null)
{
sb.AppendLine("data:");
int n = ;
if (Data.Length <= n)
{
sb.AppendLine(Encoding.UTF8.GetString(Data));
}
else
{
sb.AppendLine(Encoding.UTF8.GetString(Data, , n));
sb.AppendFormat("<--- TOO-LARGE-TO-DISPLAY --- TOTAL {0} BYTES --->", Data.Length);
sb.AppendLine();
}
} sb.AppendLine(); sb.AppendFormat("ref-code:{0}", RefCode);
sb.AppendLine(); if (!string.IsNullOrEmpty(RefText))
{
sb.AppendLine("ref-text:");
sb.AppendLine(RefText);
} sb.AppendLine(); return sb.ToString();
} #endregion
}

源码下载链接: https://pan.baidu.com/s/1bYh2COYxxeG1WIYJt6Wsnw 提取码: ysqd

最新文章

  1. getStyle(obj, attr)兼容获取css
  2. i++与++i
  3. hdu2255 二分图最大权配KM
  4. 设计模式之 -- 状态模式(State)
  5. mysql 字段引号那个像单引号的撇号用法
  6. hibernate配置文件中的catalog属性
  7. sikuli常用方法学习
  8. Linux 下Valgrind 使用
  9. 【英语】Bingo口语笔记(41) - 有关爱情的表达
  10. F5 刷新功能
  11. 为Widget添加事件
  12. bzoj 1079: [SCOI2008]着色方案 DP
  13. vim下高级操作以及文本替换命令
  14. java 乱码详解_jsp中pageEncoding、charset=UTF -8&quot;、request.setCharacterEncoding(&quot;UTF-8&quot;)
  15. 基于jsoup的Java服务端http(s)代理程序-代理服务器Demo
  16. Codeforces Round #430 (Div. 2)
  17. kettle 的表输出 table output
  18. cropper.js 裁剪图片
  19. 基于nopcommerce b2c开源项目的精简版开发框架Nop.Framework
  20. webpack 3.X研究

热门文章

  1. java构建树形列表(带children属性)
  2. IDEA设置外部比对工具Beyond Compare
  3. ExcelHelper based on NPOI
  4. 安装win10和ubuntu双系统
  5. [转载].NET ASP.NET 中web窗体(.aspx)利用ajax实现局部刷新
  6. Python【day 11】闭包
  7. vue Router——进阶篇
  8. Windows中将nginx添加到服务(转)
  9. CATransform3D 特效详解
  10. 08_28学习笔记Kotlin