1. 程式人生 > 實用技巧 >C# System.Net.Http.HttpClient使用說明

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

一、System.Net.Http.HttpClient簡介

System.Net.Http是微軟推出的最新的HTTP應用程式的程式設計介面,微軟稱之為“現代化的HTTP程式設計介面”,主要提供如下內容:

1.使用者通過HTTP使用現代化的WebService的客戶端元件

2.能夠同時在客戶端與服務端同時使用的HTTP元件(比如處理HTTP標頭和訊息),為客戶端和服務端提供一致的程式設計模型。

名稱空間System.Net.Http以及System.Net.Http.Headers提供瞭如下內容:

1.HttpClient傳送和接收HTTP請求與響應;

2.HttPR

equestMessageandHttpResponseMessage封裝了RFC2616定義的HTTP訊息;

3.HttpHeaders封裝了RFC2616定義的HTTP標頭;

4.HttpClientHandler負責生成HTTP響應訊息的HTTP處理程式。

System.Net.Http能夠處理多種型別的RFC2616定義的HTTP實體正文,如下圖所示:

  此外,System.Net.Http對HTTP訊息的處理採用了職責鏈模式,這裡有一遍不錯的介紹,這裡就不再多說了。

  System.Net.Http最早是和asp.netMvc4同時出現,是一個第三方元件,名稱是MicrosoftHTTPClientLibraries,可以在.Net4.0中使用。隨著.Net4.5的釋出,System.Net.Http正式成為.Net基礎類庫,目前已經可以在.Net4.0/4.5、WindowsPhone、以及WindowsStoreApp中使用。

  HttpClient元件類例項為一個會話傳送HTTP請求。HttpClient例項設定為集合會應用於該例項執行的所有請求。此外,每HttpClient例項使用自己的連線池,隔離其他HttpClient例項的執行請求。HttpClient也是更具體的HTTP客戶端的基類。

  預設情況下,使用HttpWebRequest向伺服器傳送請求。這一行為可通過在接受一個HttpMessageHandler例項作為引數的建構函式過載中指定不同的通道來更改。

  如果需要身份驗證或快取的功能,WebRequestHandler可使用配置項和例項傳遞給建構函式。返回的處理程式傳遞到採用HttpMessageHandler引數的某構造進行返回引數傳遞。

  如果使用HttpClient和相關元件類的app在System.Net.Http名稱空間用於下載大量資料(可達50MB或更多),則應用程式應這些下載的流和不使用預設值緩衝區。如果使用預設值緩衝區客戶端記憶體使用量會非常大,可能會導致顯著降低的效能。

  對於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響應的基類。該類可用來向WebService傳送GET、PUT、POST、DELETE以及其他請求。上述每種請求都作為非同步操作進行傳送。

  HttpResponseMessage類用於宣告從HTTP請求接收到的HTTP響應訊息。HTTP訊息由IETF在RFC2616中進行定義。

  HttpContent類是用於宣告HTTP實體正文和內容標題的基類。在這種情況下,HttpContent用於宣告HTTP響應。

  以下示例使用.NETFramework4.0的C#。同時你必須對RFC2616中詳細描述的HTTP請求有基本的瞭解。

一、建立新專案

  1.開啟MicrosoftVisualStudio2010,然後從“檔案”選單中選擇“新建專案”。在模板列表中,選擇VisualC#。在該區域下面,選擇“Windows應用程式應用”,然後選擇“空白應用程式”。將該應用程式命名為winHttpClientBase,然後單擊“確定”。

  2.新增MicrosoftHTTPClientLibraries的引用如下圖1,圖2,圖3,圖4。

圖1

圖2

圖3

圖4

二、設定啟用網路訪問的功能

  需要為應用設定網路功能,以啟用家庭網路或工作網路以及Internet的訪問。你需要為你的應用啟用網路功能,因為客戶端需要連線到因特網上的WebService。

  對於使用HttpClient連線到另一臺計算機上WebService的應用,該應用將需要設定網路功能。

三、新增Windows控制元件

  在本小節中,我們將在新增顯示資料的控制元件和內容,每個控制元件的大小和位置,我們的使用者介面如下。

  本示例使用了簡單的Windows控制元件,包括:

  o包含Label標籤、輸入URI地址的TextBox和用於啟動非同步請求的Button(請求)。

  o包一個顯示狀態與狀態程式碼的兩個Lable與TextBox。

  o包一個顯示請求結果的TextBox。用於顯示從Web服務接收到的資訊。在此示例中,HTTPGET操作的結果會以包含HTML標記的純文字顯示。

  四、建立HttpClient,傳送GET請求並檢索響應

  以下程式碼將首先建立HttpClient物件。

  1.首先建立HttpClient物件。我們還在HttpClient物件上設定兩個屬性。

  HttpClient.MaxResponseContentBufferSize屬性的預設值是整數的最大值。為了限制應用作為來自Web服務的響應接受的資料量,我們將此屬性設定為一個較小的值。

  預設情況下,HttpClient物件不會將使用者代理標識頭隨HTTP請求一起傳送到Web服務。某些HTTP伺服器(包括某些MicrosoftWeb伺服器)要求從客戶端傳送的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地址傳送HTTPGET請求並等待響應。如果發生錯誤或異常,結果會顯示在txtStatusText文字框中。如果沒有錯誤發生,則來自該Web服務的響應將顯示在txtMsg文字框中。

  如果是使用vs2012與net4.5則可以在C#和VisualBasic中使用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請求配置從代理到身份驗證的一系列選項。

一:建立新專案

  開啟MicrosoftVisualStudio2010,然後從“檔案”選單中選擇“新建專案”。在模板列表中,選擇VisualC#。在該區域下面,選擇“Windows”,然後選擇“Windows窗體應用程式”。將該應用程式命名為HttpClientHandlerSample,然後單擊“確定”。

二:新增WINDOWSUI

  在本節中,我們將在WindowsForm中定義應用的佈局,以指定應用中每個物件的大小和位置。通過新增顯示資料的控制元件和內容,我們已經完成了應用的使用者介面。如下圖。

三:建立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伺服器(包括某些MicrosoftWeb伺服器)要求從客戶端傳送的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地址傳送HTTPGET請求並等待響應。如果發生錯誤或異常,錯誤資訊會顯示在txtStatusText文字框中。如果沒有錯誤發生,則來自該Web服務的響應將顯示在txtMsg文字框中。

  說明:

  在visualstudio2012中的C#和VisualBasic中可以使用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();

            }

 

    }

 

備註

在本文中,我們介紹瞭如何將HttpClientHandlerHttpClient類結合使用,以向Web服務傳送GET請求,以及如何使用HttpResponseMessageHttpContent類檢索響應。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登入後的截圖: