C# HTTP系列9 GET与POST示例

  • 2019 年 10 月 5 日
  • 筆記

系列目录 【已更新最新开发文章,点击查看详细】

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

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

示例场景:

1 <form id="form1" runat="server" action="UserManageHandler.ashx" method="post" enctype="application/x-www-form-urlencoded">  2         <div>  3             名称: <input type="text" name="uname" class="uname" /><br />  4             邮件: <input type="text" name="email" class="email" /><br />  5                   <input type="submit" name="submit" value="提交" />  6         </div>  7  </form>
 1 using System;   2 using System.Web;   3   4 namespace SparkSoft.Platform.UI.WebForm.Test   5 {   6     public class UserManageHandler : IHttpHandler   7     {   8   9         public void ProcessRequest(HttpContext context)  10         {  11             context.Response.ContentType = "text/plain";  12  13             string uname = context.Request["uname"];  14             string email = context.Request["email"];  15  16             context.Response.Write("提交结果如下:" + Environment.NewLine +  17                                      "名称:" + uname + Environment.NewLine +  18                                      "邮箱:" + email);  19         }  20  21         public bool IsReusable  22         {  23             get { return false; }  24         }  25     }  26 }

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)。程序代码如下:

 1 /// <summary>   2 /// 普通 GET 方式请求   3 /// </summary>   4 public void Request01_ByGet()   5 {   6     HttpWebRequest httpWebRequest = WebRequest.Create("http://localhost:5000/Test/UserManageHandler.ashx?uname=zhangsan") as HttpWebRequest;   7     httpWebRequest.Method = "GET";   8   9     HttpWebResponse httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse; // 获取响应  10     if (httpWebResponse != null)  11     {  12         using (StreamReader sr = new StreamReader(httpWebResponse.GetResponseStream()))  13         {  14             string content = sr.ReadToEnd();  15         }  16  17         httpWebResponse.Close();  18     }  19 }

02 HttpWebRequest 提交数据方式2 POST方式

POST 方式通过在页面内容中填写参数的方法来完成数据的提交,

参数的格式和 GET 方式一样,是类似于 uname=zhangsan&[email protected] 这样的结构。程序代码如下:

 1 /// <summary>   2 /// 普通 POST 方式请求   3 /// </summary>   4 public void Request02_ByPost()   5 {   6     string param = "uname=zhangsan&[email protected]";              //参数   7     byte[] paramBytes = Encoding.ASCII.GetBytes(param); //参数转化为 ASCII 码   8   9     HttpWebRequest httpWebRequest = WebRequest.Create("http://localhost:5000/Test/UserManageHandler.ashx") as HttpWebRequest;  10     httpWebRequest.Method = "POST";  11     httpWebRequest.ContentType = "application/x-www-form-urlencoded";  12     httpWebRequest.ContentLength = paramBytes.Length;  13  14     using (Stream reqStream = httpWebRequest.GetRequestStream())  15     {  16         reqStream.Write(paramBytes, 0, paramBytes.Length);  17     }  18  19     HttpWebResponse httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse; // 获取响应  20     if (httpWebResponse != null)  21     {  22         using (StreamReader sr = new StreamReader(httpWebResponse.GetResponseStream()))  23         {  24             string content = sr.ReadToEnd();  25         }  26  27         httpWebResponse.Close();  28     }  29 }

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

03 HttpWebRequest 提交数据方式3 GET方式提交中文数据

GET 方式通过在网络地址中附加参数来完成数据提交,对于中文的编码,常用的有 gb2312 和 utf-8 两种。下面以 gb2312 方式编码来说明,程序代码如下:

 1 /// <summary>   2 /// 使用 GET 方式提交中文数据   3 /// </summary>   4 public void Request03_ByGet()   5 {   6     /*GET 方式通过在网络地址中附加参数来完成数据提交,对于中文的编码,常用的有 gb2312 和 utf8 两种。   7      *    由于无法告知对方提交数据的编码类型,所以编码方式要以对方的网站为标准。   8      *    常见的网站中, www.baidu.com (百度)的编码方式是 gb2312, www.google.com (谷歌)的编码方式是 utf8。   9      */  10     Encoding myEncoding = Encoding.GetEncoding("gb2312"); //确定用哪种中文编码方式  11     string address = "http://www.baidu.com/s?" + HttpUtility.UrlEncode("参数一", myEncoding) + "=" + HttpUtility.UrlEncode("值一", myEncoding); //拼接数据提交的网址和经过中文编码后的中文参数  12  13     HttpWebRequest httpWebRequest = WebRequest.Create(address) as HttpWebRequest;  14     httpWebRequest.Method = "GET";  15  16     HttpWebResponse httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse; // 获取响应  17     if (httpWebResponse != null)  18     {  19         using (StreamReader sr = new StreamReader(httpWebResponse.GetResponseStream()))  20         {  21             string content = sr.ReadToEnd();  22         }  23  24         httpWebResponse.Close();  25     }  26 }

在上面的程序代码中,我们以 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, 0, 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请求

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

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

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

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

 1 /// <summary>   2 /// HTTP请求,(不包含body数据)。   3 /// 发送 HTTP 请求并返回来自 Internet 资源的响应(HTML代码)   4 /// </summary>   5 /// <param name="url">请求目标URL</param>   6 /// <param name="method">请求的方法。请使用 WebRequestMethods.Http 的枚举值</param>   7 /// <returns>HTTP的响应结果</returns>   8 private HttpResult Request(string url, string method)   9 {  10     HttpResult httpResult = new HttpResult();  11     HttpWebRequest httpWebRequest = null;  12     try  13     {  14         httpWebRequest = WebRequest.Create(url) as HttpWebRequest;  15         httpWebRequest.Method = method;  16         httpWebRequest.UserAgent = _userAgent;  17         httpWebRequest.AllowAutoRedirect = _allowAutoRedirect;  18         httpWebRequest.ServicePoint.Expect100Continue = false;  19  20         HttpWebResponse httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse;  21         if (httpWebResponse != null)  22         {  23             GetResponse(ref httpResult, httpWebResponse);  24             httpWebResponse.Close();  25         }  26     }  27     catch (WebException webException)  28     {  29         GetWebExceptionResponse(ref httpResult, webException);  30     }  31     catch (Exception ex)  32     {  33         GetExceptionResponse(ref httpResult, ex, method, string.Empty);  34     }  35     finally  36     {  37         if (httpWebRequest != null)  38         {  39             httpWebRequest.Abort();  40         }  41     }  42  43     return httpResult;  44 }
 1 /// <summary>   2 ///  HTTP请求(包含文本的body数据)   3 /// </summary>   4 /// <param name="url">请求目标URL</param>   5 /// <param name="data">主体数据(普通文本或者JSON文本)。如果参数中有中文,请使用合适的编码方式进行编码,例如:gb2312或者utf-8</param>   6 /// <param name="method">请求的方法。请使用 WebRequestMethods.Http 的枚举值</param>   7 /// <param name="contentType"><see langword="Content-type" /> HTTP 标头的值。请使用 ContentType 类的常量来获取</param>   8 /// <returns></returns>   9 private HttpResult Request(string url, string data, string method, string contentType)  10 {  11     HttpResult httpResult = new HttpResult();  12     HttpWebRequest httpWebRequest = null;  13  14     try  15     {  16         httpWebRequest = WebRequest.Create(url) as HttpWebRequest;  17         httpWebRequest.Method = method;  18         httpWebRequest.Headers = HeaderCollection;  19         httpWebRequest.CookieContainer = CookieContainer;  20         httpWebRequest.ContentType = contentType;// 此属性的值存储在WebHeaderCollection中。如果设置了WebHeaderCollection,则属性值将丢失。所以放置在Headers 属性之后设置  21         httpWebRequest.UserAgent = _userAgent;  22         httpWebRequest.AllowAutoRedirect = _allowAutoRedirect;  23         httpWebRequest.ServicePoint.Expect100Continue = false;  24  25         if (data != null)  26         {  27             httpWebRequest.AllowWriteStreamBuffering = true;  28             using (Stream requestStream = httpWebRequest.GetRequestStream())  29             {  30                 requestStream.Write(EncodingType.GetBytes(data), 0, data.Length);//将请求参数写入请求流中  31                 requestStream.Flush();  32             }  33         }  34  35         HttpWebResponse httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse;  36         if (httpWebResponse != null)  37         {  38             GetResponse(ref httpResult, httpWebResponse);  39             httpWebResponse.Close();  40         }  41     }  42     catch (WebException webException)  43     {  44         GetWebExceptionResponse(ref httpResult, webException);  45     }  46     catch (Exception ex)  47     {  48         GetExceptionResponse(ref httpResult, ex, method, contentType);  49     }  50     finally  51     {  52         if (httpWebRequest != null)  53         {  54             httpWebRequest.Abort();  55         }  56     }  57  58     return httpResult;  59 }

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

  1 /// <summary>    2 ///  HTTP请求(GET,POST等)的响应返回消息    3 /// </summary>    4 public sealed class HttpResult    5 {    6     #region  字段    7    8     /// <summary>    9     ///  HTTP 响应成功,即状态码为200   10     /// </summary>   11     public const string STATUS_SUCCESS = "success";   12   13     /// <summary>   14     ///  HTTP 响应失败   15     /// </summary>   16     public const string STATUS_FAIL = "fail";   17   18     #endregion   19   20     #region 属性   21   22     /// <summary>   23     ///  获取或设置请求的响应状态,success 或者 fail。建议使用常量:HttpResult.STATUS_SUCCESS 与 HttpResult.STATUS_FAIL   24     /// </summary>   25     public string Status { get; set; }   26   27     /// <summary>   28     ///  获取或设置请求的响应状态描述   29     /// </summary>   30     public string StatusDescription { get; set; }   31   32     /// <summary>   33     /// 状态码。与 HttpWebResponse.StatusCode 完全相同   34     /// </summary>   35     public int? StatusCode { get; set; }   36   37     /// <summary>   38     /// 响应消息或错误文本   39     /// </summary>   40     public string Text { get; set; }   41   42     /// <summary>   43     /// 响应消息或错误(二进制格式)   44     /// </summary>   45     public byte[] Data { get; set; }   46   47     /// <summary>   48     /// 参考代码(用户自定义)。   49     /// 当 Status 等于 success 时,该值为 null;   50     /// 当 Status 等于 fail 时,该值为程序给出的用户自定义编码。   51     /// </summary>   52     public int? RefCode { get; set; }   53   54     /// <summary>   55     /// 附加信息(用户自定义内容,如Exception内容或者自定义提示信息)。   56     /// 当 Status 等于 success 时,该值为为空   57     /// 当 Status 等于 fail 时,该值为程序给出的用户自定义内容,如Exception内容或者自定义提示信息。   58     /// </summary>   59     public string RefText { get; set; }   60   61     /// <summary>   62     ///  获取或设置Http的请求响应。   63     /// </summary>   64     public HttpWebResponse HttpWebResponse { get; set; }   65   66     ///// <summary>   67     ///// 参考信息(从返回消息 WebResponse 的头部获取)   68     ///// </summary>   69     //public Dictionary<string, string> RefInfo { get; set; }   70   71     #endregion   72   73     #region 构造函数   74     /// <summary>   75     /// 初始化(所有成员默认值,需要后续赋值)   76     /// </summary>   77     public HttpResult()   78     {   79         Status = string.Empty;   80         StatusDescription = string.Empty;   81         StatusCode = null;   82         Text = string.Empty;   83         Data = null;   84   85         RefCode = null;   86         RefText = string.Empty;   87         //RefInfo = null;   88   89         HttpWebResponse = null;   90     }   91   92     #endregion   93   94     #region 方法   95   96     /// <summary>   97     /// 对象复制   98     /// </summary>   99     /// <param name="httpResultSource">要复制其内容的来源</param>  100     public void Shadow(HttpResult httpResultSource)  101     {  102         this.Status = httpResultSource.Status;  103         this.StatusDescription = string.Empty;  104         this.StatusCode = httpResultSource.StatusCode;  105         this.Text = httpResultSource.Text;  106         this.Data = httpResultSource.Data;  107  108         this.RefCode = httpResultSource.RefCode;  109         this.RefText += httpResultSource.RefText;  110         //this.RefInfo = httpResultSource.RefInfo;  111  112         this.HttpWebResponse = httpResultSource.HttpWebResponse;  113     }  114  115     /// <summary>  116     /// 转换为易读或便于打印的字符串格式  117     /// </summary>  118     /// <returns>便于打印和阅读的字符串</returns>  119     public override string ToString()  120     {  121         StringBuilder sb = new StringBuilder();  122  123         sb.AppendFormat("Status:{0}", Status);  124         sb.AppendFormat("StatusCode:{0}", StatusCode);  125         sb.AppendFormat("StatusDescription:{0}", StatusDescription);  126         sb.AppendLine();  127  128         if (!string.IsNullOrEmpty(Text))  129         {  130             sb.AppendLine("text:");  131             sb.AppendLine(Text);  132         }  133  134         if (Data != null)  135         {  136             sb.AppendLine("data:");  137             int n = 1024;  138             if (Data.Length <= n)  139             {  140                 sb.AppendLine(Encoding.UTF8.GetString(Data));  141             }  142             else  143             {  144                 sb.AppendLine(Encoding.UTF8.GetString(Data, 0, n));  145                 sb.AppendFormat("<--- TOO-LARGE-TO-DISPLAY --- TOTAL {0} BYTES --->", Data.Length);  146                 sb.AppendLine();  147             }  148         }  149  150         sb.AppendLine();  151  152         sb.AppendFormat("ref-code:{0}", RefCode);  153         sb.AppendLine();  154  155         if (!string.IsNullOrEmpty(RefText))  156         {  157             sb.AppendLine("ref-text:");  158             sb.AppendLine(RefText);  159         }  160  161         sb.AppendLine();  162  163         return sb.ToString();  164     }  165  166     #endregion  167 }

系列目录 【已更新最新开发文章,点击查看详细】