C# HTTP系列9 GET與POST示例

學習本篇以前,對 HttpWebRequest 與 HttpWebResponse 不太熟悉的同窗,請先學習《C# HTTP系列》。html

應用程序中使用HTTP協議和服務器交互主要是進行數據的上傳與下載,最多見的方式是經過 GET 和 POST 兩種方式來完成。本篇介紹 C# HttpWebRequest 如何使用這兩種方式來實現。web

示例場景:服務器

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=123456@qq.com 這樣的結構。程序代碼以下:網絡

 1 /// <summary>
 2 /// 普通 POST 方式請求
 3 /// </summary>
 4 public void Request02_ByPost()
 5 {
 6     string param = "uname=zhangsan&email=123456@qq.com";              //參數
 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 }

若是提交的請求參數中包含中文,那麼須要對其進行編碼,讓目標網站可以識別。 app

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。ide

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個方法調用了公用的業務方法,分別以下:post

 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 }
View Code

 

相關文章
相關標籤/搜索