• C# HTTP系列9 GET与POST示例


    学习本篇之前,对 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=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 }

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

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

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

  • 相关阅读:
    2019/3/20统计单词数
    2019/3/20日历问题
    2019/3/20计算器1
    2019/3/17素数因子
    2019/3/17日历问题2
    2019/2/14多项式输出
    2019/2/13打印华氏温度与摄氏温度对照表
    2019/2/12孪生素数
    2019/2/12开灯问题
    2019/2/11 6084问题
  • 原文地址:https://www.cnblogs.com/SavionZhang/p/11413218.html
Copyright © 2020-2023  润新知