學習本篇以前,對 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 }
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 }
參數的格式和 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
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
/// <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 的場景下。函數
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 }
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 }