C# System.Net.Http.HttpClient使用说明

一、 System.Net.Http.HttpClient简介

System.Net.Http 是微软推出的最新的 HTTP 应用程序的编程接口, 微软称之为“现代化的 HTTP 编程接口”, 主要提供如下内容:

1. 用户通过 HTTP 使用现代化的 Web Service 的客户端组件

2. 能够同时在客户端与服务端同时使用的 HTTP 组件(比如处理 HTTP 标头和消息), 为客户端和服务端提供一致的编程模型。

 

命名空间 System.Net.Http 以及 System.Net.Http.Headers 提供了如下内容:

1. HttpClient 发送和接收 HTTP 请求与响应;

2. HttPRequestMessage and HttpResponseMessage 封装了 RFC 2616 定义的 HTTP 消息;

3. HttpHeaders 封装了 RFC 2616 定义的 HTTP 标头;

4. HttpClientHandler 负责生成HTTP响应消息的HTTP处理程序。

System.Net.Http 能够处理多种类型的 RFC 2616 定义的 HTTP 实体正文, 如下图所示:

 

 

  此外, System.Net.Http 对 HTTP 消息的处理采用了职责链模式, 这里有一遍不错的介绍, 这里就不再多说了。

 

  System.Net.Http 最早是和 asp.net Mvc4 同时出现, 是一个第三方组件,名称是Microsoft HTTP Client Libraries,可以在 .Net 4.0 中使用。 随着 .Net 4.5 的发布, System.Net.Http 正式成为 .Net 基础类库, 目前已经可以在 .Net 4.0/4.5 、 Windows Phone 、 以及 Windows Store App 中使用。 

  HttpClient 组件类实例为一个会话发送 HTTP 请求。 HttpClient 实例设置为集合会应用于该实例执行的所有请求。 此外,每 HttpClient 实例使用自己的连接池,隔离其他 HttpClient实例的执行请求。 HttpClient 也是更具体的 HTTP 客户端的基类。 

  默认情况下,使用 HttpWebRequest 向服务器发送请求。 这一行为可通过在接受一个HttpMessageHandler实例作为参数的构造函数重载中指定不同的通道来更改。

  如果需要身份验证或缓存的功能,WebRequestHandler 可使用配置项和实例传递给构造函数。 返回的处理程序传递到采用 HttpMessageHandler 参数的某构造进行返回参数传递。 

  如果使用 HttpClient 和相关组件类的 app 在 System.Net.Http 命名空间用于下载大量数据 (可达 50 MB 或更多),则应用程序应这些下载的流和不使用默认值缓冲区。 如果使用默认值缓冲区客户端内存使用量会非常大,可能会导致显着降低的性能。 

  

  对于 HttpClient的基本使用方法,示例代码如下:

//声明HttpClient

HttpClient client = new HttpClient

{

BaseAddress = new Uri("http://www.163.com")

};

//多线程中跨线程进行信息显示委托

public delegate void ShowMsgDelegate(string text);

public void ShowMsgText(string text)

{

txtMsg.Text=text;

}

//信息显示

private void ShowMessage(string msg)

{

if (this.InvokeRequired)

{

this.Invoke(new ShowMsgDelegate(ShowMsgText), msg);

}

else

{

ShowMsgText(msg);

}

}

 

// Get form data to server

 

private void btnGet_Click(object sender, EventArgs e)

{

// Get string from server

client.GetStringAsync("browserhttp/").ContinueWith(t =>

{

if (t.IsFaulted)

{

ShowMessage("返回信息错误:" + t.Result);

}

else

{

ShowMessage("成功:" + t.Result);

}

});

}

 

 

 

// Post form data to server

 

private void btnPost_Click(object sender, EventArgs e)

{

var param = new Dictionary<string, string> {

{"Name", "TOM Post"},

{"Age", "11"},

{"Birthday", DateTime.Now.ToString("yyyyMMdd")}

};

 

client.PostAsync("browserhttp/", new FormUrlEncodedContent(param)).ContinueWith(t =>

{

ShowMsgDelegate showmsg = new ShowMsgDelegate(ShowMsgText);

if (t.IsFaulted)

{

ShowMessage("返回信息错误:" + t.Result);

 

}

else

{

HttpResponseMessage response = t.Result;

ShowMessage(response.StatusCode.ToString());

}

});

 

}

// PUT to update

private void btnPut_Click(object sender, EventArgs e)

{

var param = new Dictionary<string, string> {

{"Id", "10" },

{"Name", "Tom Post"},

{"Age", "10"},

{"Birthday", DateTime.Now.ToString("yyyyMMdd")}

};

client.PutAsync("clienthttp/1", new FormUrlEncodedContent(param)).ContinueWith(t =>

{

if (t.IsFaulted)

{

ShowMessage("返回信息错误:" + t.Result);

}

else

{

HttpResponseMessage response = t.Result;

ShowMessage(response.StatusCode.ToString());

}

});

}

 

// DELETE

 

private void btnDel_Click(object sender, EventArgs e)

{

client.DeleteAsync("clienthttp/1").ContinueWith(t =>

{

if (t.IsFaulted)

{

ShowMessage("返回信息错误:" + t.Result);

 

}

else

{

HttpResponseMessage response = t.Result;

ShowMessage(response.StatusCode.ToString());

}

});

}

支持职责链模式的 MessageProcessingHandler ,MessageProcessingHandler - 一种基本的 HTTP 消息处理程序。这是最容易进行派生的处理程序,应该作为大多数自定义处理程序的起点。 自已定义了一个新的MessageProcessingHandler处理程序,如下面的示例代码所示:

public class CustomProcessingHandler : MessageProcessingHandler {

 

protected override HttpRequestMessage ProcessRequest(HttpRequestMessage request, CancellationToken cancellationToken) {

if (request.Method != HttpMethod.Get && request.Method != HttpMethod.Post) {

request.Headers.TryAddWithoutValidation("RequestMethod", request.Method.Method);

request.Method = HttpMethod.Post;

}

return request;

}

 

protected override HttpResponseMessage ProcessResponse(HttpResponseMessage response, CancellationToken cancellationToken) {

var request = response.RequestMessage;

if (request.Headers.Contains("RequestMethod")) {

IEnumerable<string> values;

if (request.Headers.TryGetValues("RequestMethod", out values)) {

request.Method = new HttpMethod(values.First());

}

}

return response;

}

}

  使用起来也是非常简单的:

private void btnCustom_Click(object sender, EventArgs e)

{

var customHandler = new CustomProcessingHandler

{

InnerHandler = new HttpClientHandler()

};

 

var client = new HttpClient(customHandler, true)

{

BaseAddress = new Uri("http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl")

};

var task = client.GetAsync(client.BaseAddress);

task.Result.EnsureSuccessStatusCode();

HttpResponseMessage response = task.Result;

txtStatusCode.Text = response.StatusCode + " " + response.ReasonPhrase + Environment.NewLine;

txtStatusText.Text = "请求返回结果如下 ...";

var result = response.Content.ReadAsStringAsync();

txtMsg.Text = result.Result; ;

 

}

二、使用 HttpClient 进行连接

使用 HttpClient 进行连接

  使用 System.Net.Http 命名空间中的 HttpClient 类可以向 WebService发送 POST与GET 请求并检索响应数据。

 

  System.Net.Http 命名空间中的类可为现代 HTTP 应用提供编程接口。System.Net.Http 命名空间和相关的 System.Net.Http.Headers 命名空间提供的 HTTP 客户端组件,允许用户通过 HTTP 使用现代的 WebService。

 

  HttpClient 类用于通过 HTTP 发送和接收基本要求。它提供了一个用于从 URI 所标识的资源发送 HTTP 请求和接收 HTTP 响应的基类。该类可用来向 Web Service发送 GET、PUT、POST、DELETE 以及其他请求。上述每种请求都作为异步操作进行发送。

 

  HttpResponseMessage 类用于声明从 HTTP 请求接收到的 HTTP 响应消息。HTTP 消息由 IETF 在 RFC 2616 中进行定义。 

 

  HttpContent 类是用于声明 HTTP 实体正文和内容标题的基类。 在这种情况下,HttpContent 用于声明 HTTP 响应。

 

 

 

  以下示例使用 .NET Framework 4.0 的 C#。同时你必须对 RFC 2616 中详细描述的 HTTP 请求有基本的了解。

 

一、 创建新项目

 

  1. 打开 Microsoft Visual Studio 2010,然后从“文件”菜单中选择“新建项目”。在模板列表中,选择 Visual C#。在该区域下面,选择“Windows 应用程序应用”,然后选择“空白应用程序”。将该应用程序命名为 winHttpClientBase,然后单击“确定”。

 

  2. 添加Microsoft HTTP Client Libraries的引用如下图1,图2,图3,图4。

 

 

 

图1

 

 

 

 

 

图2

 

 

 

图3

 

 

 

 

 

图4

 

二、设置启用网络访问的功能

 

  需要为应用设置网络功能,以启用家庭网络或工作网络以及 Internet 的访问。你需要为你的应用启用网络功能,因为客户端需要连接到因特网上的 Web Service。

 

  对于使用 HttpClient 连接到另一台计算机上 Web Service的应用,该应用将需要设置网络功能。

 

三、添加 Windows 控件 

 

  在本小节中,我们将在添加显示数据的控件和内容,每个控件的大小和位置,我们的用户界面如下。

 

 

  本示例使用了简单的 Windows 控件,包括:

 

  o 包含Label 标签、输入 URI 地址的 TextBox和用于启动异步请求的Button(请求) 。

 

  o 包一个显示状态与状态代码的两个Lable与TextBox。

 

  o 包一个显示请求结果的TextBox。用于显示从 Web 服务接收到的信息。在此示例中,HTTP GET 操作的结果会以包含 HTML 标记的纯文本显示。

 

 

 

 

 

  四、创建 HttpClient,发送 GET 请求并检索响应

 

  以下代码将首先创建 HttpClient 对象。

 

  1. 首先创建 HttpClient 对象。我们还在 HttpClient 对象上设置两个属性。

 

  HttpClient.MaxResponseContentBufferSize 属性的默认值是整数的最大值。为了限制应用作为来自 Web 服务的响应接受的数据量,我们将此属性设置为一个较小的值。

 

  默认情况下,HttpClient 对象不会将用户代理标识头随 HTTP 请求一起发送到 Web 服务。某些 HTTP 服务器(包括某些 Microsoft Web 服务器)要求从客户端发送的 HTTP 请求附带用户代理标识头,并且如果没有标识头,则返回错误。为了避免这些错误,使用 HttpClient.DefaultRequestHeaders 属性添加了用户代理标头。

 

  2. 打开 Form1.cs 文件。然后将如下代码添加到该文件中。

 

   

 

复制代码
复制代码
   private void btnRequest_Click(object sender, EventArgs e)

        {

            Init();

        }

        private HttpClient httpClient;

 

    public void Init()

    {

        this.InitializeComponent();

        httpClient = new HttpClient();

        // Limit the max buffer size for the response so we don't get overwhelmed

        httpClient.MaxResponseContentBufferSize = 256000;

        httpClient.DefaultRequestHeaders.Add("user-agent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)");

    }

 

 

 
复制代码
复制代码

 

 

 

 

 

  3. 发送 GET 请求并检索响应。

 

  在单击“请求”按钮之后, txtStatusText和 txtMsg文本框中的文本将被更新,然后应用程序使用txtUrl文本框中的 URI 地址发送 HTTP GET 请求并等待响应。如果发生错误或异常,结果会显示在 txtStatusText文本框中。如果没有错误发生,则来自该 Web 服务的响应将显示在 txtMsg文本框中。

 

  如果是使用vs 2012与net 4.5 则可以在 C# 和 Visual Basic 中使用 await 关键字时,发送 GET 请求并异步检索响应的代码与我们用于同步完成该操作的代码相似。只有在该方法被定义为 async 时,才能使用 await 关键字。

 

  如果 Web 服务器返回 HTTP 错误状态代码,则 HttpResponseMessage.EnsureSuccessStatusCode 方法将引发异常。 如果发生错误,则对任何异常使用 try/catch 块,并在 txtStatusText 文本框中显示异常信息。在 try 块中,显示 Web 服务所返回的状态(txtStatusText)和状态代码(txtStatusCode)。

 

  HttpResponseMessage.Content 属性声明 HTTP 响应的内容。HttpContent.ReadAsStringAsync 方法将 HTTP 内容作为异步操作写入到字符串中。 为了方便显示,我们将所返回的 HTML 文本中的所有 <br> 标记都替换成了新行。

 

 

 

 

 

复制代码
复制代码
 

         private  void GetHtml()

        {

            try

            {

                string responseBodyAsText;

                txtMsg.Text = "";

                txtStatusText.Text = "Waiting for response ...";

                var task = httpClient.GetAsync(new Uri(txtUrl.Text));

                task.Result.EnsureSuccessStatusCode();

                //var result = task.Result.Content.ReadAsStringAsync();

                HttpResponseMessage response = task.Result;

                 

                

                

                txtStatusText.Text = response.StatusCode + " " + response.ReasonPhrase + Environment.NewLine;

                var result =  response.Content.ReadAsStringAsync();

                responseBodyAsText = result.Result;

                responseBodyAsText = responseBodyAsText.Replace("<br>", Environment.NewLine); // Insert new lines

                txtMsg.Text = responseBodyAsText;

            }

            catch (HttpRequestException hre)

            {

                txtStatusText.Text = hre.ToString();

            }

            catch (Exception ex)

            {

                // For debugging

                txtStatusText.Text = ex.ToString();

            }

        }

 

 
复制代码
复制代码

 

 

 

  如果使用 System.Net.Http 命名空间中的 HttpClient 和相关类的应用用于下载大量数据(50M 或更多),则该应用应流式传输这些下载内容并且不使用默认缓冲。如果使用了默认缓冲,则客户端内存使用量将变得非常大,这可能会导致大幅度降低性能。

 

  当 HttpClient 类和相关类的成员检测到无效的统一资源标识符 (URI) 时,则将引发 UriFormatException 此例外不可以在 Windows 应用商店应用中使用。若要在这种情况下捕获此例外,请为 FormatException 编写捕获语句。 

 

 

 

 

 

五、小结

 

  在本文中,我们已了解如何使用 HttpClient 类向 Web 服务发送 GET 请求以及如何使用 HttpResponseMessage 和 HttpContent 类检索响应。

 

  HttpClientBasic 完整示例

 

 

 

复制代码
复制代码
public partial class Form1 : Form

    {

        public Form1()

        {

            InitializeComponent();

        }

 

        private void btnRequest_Click(object sender, EventArgs e)

        {

            Init();

            GetHtml();

        }

 

        private void GetHtml()

        {

            try

            {

                string responseBodyAsText;

                txtMsg.Text = "";

                txtStatusText.Text = "等待请求返回 ...";

                var task = httpClient.GetAsync(new Uri(txtUrl.Text));

                task.Result.EnsureSuccessStatusCode();

                HttpResponseMessage response = task.Result;

                txtStatusCode.Text = response.StatusCode + " " + response.ReasonPhrase + Environment.NewLine;

                txtStatusText.Text = "请求返回结果如下 ...";

                var result = response.Content.ReadAsStringAsync();

                responseBodyAsText = result.Result;

                responseBodyAsText = responseBodyAsText.Replace("<br>", Environment.NewLine); // Insert new lines

 

                txtMsg.Text = responseBodyAsText;

            }

            catch (HttpRequestException hre)

            {

                txtStatusText.Text = hre.ToString();

            }

            catch (Exception ex)

            {

                // For debugging

                txtStatusText.Text = ex.ToString();

            }

        }

 

 

        private HttpClient httpClient;

 

        public void Init()

        {

 

            httpClient = new HttpClient();            

            httpClient.MaxResponseContentBufferSize = 256000;

            httpClient.DefaultRequestHeaders.Add("user-agent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)");

        }

    }

 
复制代码
复制代码

 

 

 

可以将 HttpClientHandler 类与 HttpClient 类结合使用,以设置有关 HTTP 请求的选项。 

 

 

 

 

 

 

三、使用 HttpClient 检索与获取过程数据

 

如何使用 HttpClient 处理程序

 

  将 HttpClientHandler 类与 System.Net.Http 命名空间中的 HttpClient 类结合使用,以向 Web Service发送 GET 请求并检索响应。

 

  HttpClient 类用于通过 HTTP 发送和接收基本要求。它提供了一个用于从 URI 所标识的资源发送 HTTP 请求和接收 HTTP 响应的基类。该类可用来向 Web 服务发送 GET、PUT、POST、DELETE 以及其他请求。上述每种请求都作为异步操作进行发送。

 

  HttpClientHandler 类是 HttpClient 的默认消息处理程序。HttpClientHandler 类以及从该类派生的类让开发人员可以对 HTTP 请求配置从代理到身份验证的一系列选项。

 

一: 创建新项目

 

  打开 Microsoft Visual Studio 2010,然后从“文件”菜单中选择“新建项目”。在模板列表中,选择 Visual C#。在该区域下面,选择“Windows”,然后选择“Windows窗体应用程序”。将该应用程序命名为 HttpClientHandlerSample,然后单击“确定”。

 

二: 添加 WINDOWS UI 

 

   在本节中,我们将在 Windows Form 中定义应用的布局,以指定应用中每个对象的大小和位置。 通过添加显示数据的控件和内容,我们已经完成了应用的用户界面。如下图。

 

 

 

 

 

三: 创建 HttpClientHandler,发送 GET 请求并检索响应

 

  以下示例代码将首先创建 HttpClientHandler 对象。该代码还将对该对象设置一个属性,并使用 HttpClientHandler 创建一个 HttpClient 对象。

 

  1. 首先创建 HttpClientHandler 对象。将 AllowAutoRedirect 属性设置为 false。此示例显示了如何使用 HttpClientHandler 属性来设置有关 HTTP 请求的选项。

 

  AllowAutoRedirect 属性指示 HttpClientHandler 对象的请求是否应遵循重定向响应。此属性的默认值是 true。如果此属性被设置为 false,则不会遵循 Web 服务的重定向请求。

 

  然后,使用 HttpClientHandler 对象创建 HttpClient 对象。我们还在 HttpClient 对象上设置两个属性。HttpClient.MaxResponseContentBufferSize 属性的默认大小是整数的最大大小。为了限制应用作为来自 Web 服务的响应接受的数据量,我们将此属性设置为一个较小的值。

 

  默认情况下,HttpClient 对象不会将用户代理标头随 HTTP 请求一起发送到 Web 服务。某些 HTTP 服务器(包括某些 Microsoft Web 服务器)要求从客户端发送的 HTTP 请求附带用户代理标头,并且如果没有标头,则返回错误。为了避免这些错误,示例使用 HttpClient.DefaultRequestHeaders 属性添加了用户代理标头。

 

  打开 Form1.cs 文件,然后将如下代码添加到该文件中。

 

 

 

复制代码
复制代码
   private HttpClient httpClient;

    private HttpClientHandler handler;

 

    public void Init()

    {

        txtUrl.Text = "http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl";

        handler = new HttpClientHandler();

        handler.AllowAutoRedirect=false; 

 

        httpClient = new HttpClient(handler);

 

        // Limit the max buffer size for the response so we don't get overwhelmed

        httpClient.MaxResponseContentBufferSize = 256000;

        // Add a user-agent header

        httpClient.DefaultRequestHeaders.Add("user-agent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)");

    }
复制代码
复制代码

 

 

 

   2. 发送 GET 请求并检索响应。

 

  在单击“请求”按钮之后,txtStatusText 和 txtMsg两个文本框中的文本将被更新,然后使用输入到txtUrl文本框中的 URI 地址发送 HTTP GET 请求并等待响应。如果发生错误或异常,错误信息会显示在 txtStatusText文本框中。如果没有错误发生,则来自该 Web 服务的响应将显示在 txtMsg文本框中。

 

  说明:

 

  在  visual studio 2012 中的 C# 和 Visual Basic 中可以使用 await 关键字时,发送 GET 请求并异步检索响应的代码与我们用于同步完成该操作的代码相似。只有在该方法被定义为 async 时,才能使用 await 关键字。

 

  如果 Web 服务器返回 HTTP 错误状态代码,则 HttpResponseMessage.EnsureSuccessStatusCode 方法将引发异常。 如果发生错误,则对任何异常使用 try/catch 块,并把错误信息显示在txtStatusText 文本框中的异常消息。在 try 块中,显示 Web 服务所返回的状态和响应。

 

  HttpResponseMessage.Content 属性声明 HTTP 响应的内容。HttpContent.ReadAsStringAsync 方法将 HTTP 内容作为异步操作写入到字符串中。 

 

 

 

  

 

复制代码
复制代码
    private void btnRequest_Click(object sender, EventArgs e)

    {

           try

            {

                

                txtMsg.Text=string.Empty;

                txtStatusText.Text = "等待请求返回 ...";

                var task = httpClient.GetAsync(txtUrl.Text);

                task.Result.EnsureSuccessStatusCode();

                HttpResponseMessage response = task.Result;

                

             

                txtStatusCode.Text = response.StatusCode + " " + response.ReasonPhrase + Environment.NewLine;

                txtStatusText.Text = "请求返回结果如下 ...";

                var result = response.Content.ReadAsStringAsync();

               string responseBodyAsText = result.Result;

                responseBodyAsText = responseBodyAsText.Replace("<br>", Environment.NewLine); // Insert new lines

 

                txtMsg.Text=responseBodyAsText;

            }

            catch (HttpRequestException hre)

            {

                txtStatusText.Text = hre.ToString();

            }

            catch (Exception ex)

            {


                txtStatusText.Text = ex.ToString();

            }

 

    }

 
复制代码
复制代码

 

 

 

 

 

 

 

 

 

备注

 

在本文中,我们介绍了如何将 HttpClientHandler 与 HttpClient 类结合使用,以向 Web 服务发送 GET 请求,以及如何使用 HttpResponseMessage 和 HttpContent 类检索响应。HttpClientHandler 允许应用设置有关 HTTP 请求的选项。

 

有一些 HTTP 消息处理程序可以与 HttpClient 类结合使用。

 

  • HttpClientHandler - 本文中 HttpClient 所用的默认消息处理程序。
  • MessageProcessingHandler - 一种基本的 HTTP 消息处理程序。这是最容易进行派生的处理程序,应该作为大多数自定义处理程序的起点。
  • DelegatingHandler - 一种基本的 HTTP 处理程序,可将 HTTP 响应消息的处理委派给其他处理程序。

 

 

 

完整示例:

 

 

 

 

 

复制代码
复制代码
HttpClientHandler 示例
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Http;

namespace HttpClientHandlerSample
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            Init();
        }

          private HttpClient httpClient;
    private HttpClientHandler handler;

    public void Init()
    {
        txtUrl.Text = "http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl";
        handler = new HttpClientHandler();
        handler.AllowAutoRedirect=false; 

        httpClient = new HttpClient(handler);

        // Limit the max buffer size for the response so we don't get overwhelmed
        httpClient.MaxResponseContentBufferSize = 256000;
        // Add a user-agent header
        httpClient.DefaultRequestHeaders.Add("user-agent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)");
    }

    private void btnRequest_Click(object sender, EventArgs e)
    {
           try
            {
                
                txtMsg.Text=string.Empty;
                txtStatusText.Text = "等待请求返回 ...";
                var task = httpClient.GetAsync(txtUrl.Text);
                task.Result.EnsureSuccessStatusCode();
                HttpResponseMessage response = task.Result;
                
             
                txtStatusCode.Text = response.StatusCode + " " + response.ReasonPhrase + Environment.NewLine;
                txtStatusText.Text = "请求返回结果如下 ...";
                var result = response.Content.ReadAsStringAsync();
               string responseBodyAsText = result.Result;
                responseBodyAsText = responseBodyAsText.Replace("<br>", Environment.NewLine); // Insert new lines

                txtMsg.Text=responseBodyAsText;
            }
            catch (HttpRequestException hre)
            {
                txtStatusText.Text = hre.ToString();
            }
            catch (Exception ex)
            {
                txtStatusText.Text = ex.ToString();
            }
    }
    }
}
复制代码
复制代码

 

 

四、实例(模拟post登录博客园)

 

首先,需要说明的是,本实例环境是win7 64位+vs 2013+ .net 4.5框架。

 

1.使用vs2013新建一个控制台程序,或者窗体程序,如下图所示:

 

 

 

 

2.必须引入System.Net.Http框架,否则将不能使用httpclient

 

 

 

 

 

 

 

3.实现代码

 

复制代码
复制代码
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace ClassLibrary1
{
    public class Class1
    {
        private static String dir = @"C:\work\";

        /// <summary>
        /// 写文件到本地
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="html"></param>
        public static void Write(string fileName, string html)
        {
            try
            {
                FileStream fs = new FileStream(dir + fileName, FileMode.Create);
                StreamWriter sw = new StreamWriter(fs, Encoding.Default);
                sw.Write(html);
                sw.Close();
                fs.Close();

            }catch(Exception ex){
                Console.WriteLine(ex.StackTrace);
            }
           
        }

        /// <summary>
        /// 写文件到本地
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="html"></param>
        public static void Write(string fileName, byte[] html)
        {
            try
            {
                File.WriteAllBytes(dir + fileName, html);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.StackTrace);
            }
            
        }

        /// <summary>
        /// 登录博客园
        /// </summary>
        public static void LoginCnblogs()
        {
            HttpClient httpClient = new HttpClient();
            httpClient.MaxResponseContentBufferSize = 256000;
            httpClient.DefaultRequestHeaders.Add("user-agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36");
            String url = "http://passport.cnblogs.com/login.aspx";
            HttpResponseMessage response = httpClient.GetAsync(new Uri(url)).Result;
            String result = response.Content.ReadAsStringAsync().Result;

            String username = "hi_amos";
            String password = "密码";

            do
            {
                String __EVENTVALIDATION = new Regex("id=\"__EVENTVALIDATION\" value=\"(.*?)\"").Match(result).Groups[1].Value;
                String __VIEWSTATE = new Regex("id=\"__VIEWSTATE\" value=\"(.*?)\"").Match(result).Groups[1].Value;
                String LBD_VCID_c_login_logincaptcha = new Regex("id=\"LBD_VCID_c_login_logincaptcha\" value=\"(.*?)\"").Match(result).Groups[1].Value;

                //图片验证码
                url = "http://passport.cnblogs.com" + new Regex("id=\"c_login_logincaptcha_CaptchaImage\" src=\"(.*?)\"").Match(result).Groups[1].Value;
                response = httpClient.GetAsync(new Uri(url)).Result;
                Write("amosli.png", response.Content.ReadAsByteArrayAsync().Result);
                
                Console.WriteLine("输入图片验证码:");
                String imgCode = "wupve";//验证码写到本地了,需要手动填写
                imgCode =  Console.ReadLine();

                //开始登录
                url = "http://passport.cnblogs.com/login.aspx";
                List<KeyValuePair<String, String>> paramList = new List<KeyValuePair<String, String>>();
                paramList.Add(new KeyValuePair<string, string>("__EVENTTARGET", ""));
                paramList.Add(new KeyValuePair<string, string>("__EVENTARGUMENT", ""));
                paramList.Add(new KeyValuePair<string, string>("__VIEWSTATE", __VIEWSTATE));
                paramList.Add(new KeyValuePair<string, string>("__EVENTVALIDATION", __EVENTVALIDATION));
                paramList.Add(new KeyValuePair<string, string>("tbUserName", username));
                paramList.Add(new KeyValuePair<string, string>("tbPassword", password));
                paramList.Add(new KeyValuePair<string, string>("LBD_VCID_c_login_logincaptcha", LBD_VCID_c_login_logincaptcha));
                paramList.Add(new KeyValuePair<string, string>("LBD_BackWorkaround_c_login_logincaptcha", "1"));
                paramList.Add(new KeyValuePair<string, string>("CaptchaCodeTextBox", imgCode));
                paramList.Add(new KeyValuePair<string, string>("btnLogin", "登  录"));
                paramList.Add(new KeyValuePair<string, string>("txtReturnUrl", "http://home.cnblogs.com/"));
                response = httpClient.PostAsync(new Uri(url), new FormUrlEncodedContent(paramList)).Result;
                result = response.Content.ReadAsStringAsync().Result;
                Write("myCnblogs.html",result);
            } while (result.Contains("验证码错误,麻烦您重新输入"));

            Console.WriteLine("登录成功!");
            
            //用完要记得释放
            httpClient.Dispose();
        }

        public static void Main()
        {
              LoginCnblogs();
        }

}
复制代码
复制代码

 

 

 

 

 

代码分析:

 

首先,从Main函数开始,调用LoginCnblogs方法;

 

其次,使用GET方法:

 

 HttpResponseMessage response = httpClient.GetAsync(new Uri(url)).Result;
 String result = response.Content.ReadAsStringAsync().Result;

 

再者,使用POST方法:

 

  List<KeyValuePair<String, String>> paramList = new List<KeyValuePair<String, String>>();
                paramList.Add(new KeyValuePair<string, string>("__EVENTTARGET", ""));
  ....
                response = httpClient.PostAsync(new Uri(url), new FormUrlEncodedContent(paramList)).Result;
                result = response.Content.ReadAsStringAsync().Result;

 

最后,注意其返回值可以是string,也可以是byte[],和stream的方式,这里看你需要什么吧。

 

 

 

 

4.登录成功后的截图

 

1).使用浏览器登录后的截图:

 

 

2).使用Httpcliet登录后的截图:

 

 

posted on 2020-09-16 09:42  HOT SUMMER  阅读(1117)  评论(0编辑  收藏  举报

导航