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 (Google)的編碼方式是 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 (Google)的編碼方式是 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 }

系列目錄 【已更新最新開發文章,點擊查看詳細】