Web能夠打下天下,最重要的功臣就是HTTP;HTTP能夠建功立業,最重要的原因就是它的簡單。
微軟在.NET Framework 4.5中為大家帶來了System.Net.Http.HttpClient,既然叫HttpClient,我想應該迎合了HTTP簡單的特性,應該會比HttpWebRequest更簡單。
在之前的博文“jQuery能做到,PHP能做到,C#也能做到”中也的確發現用HttpClient發起HTTP POST請求並傳遞url query string參數,比用HttpWebRequest更簡單。於是打算把基於HttpWebRequest的實現改為基於HttpClient的實現。
基於HttpWebRequest的實現中有設置UserAgent的代碼:
var webRequest = WebRequest.Create(url) as HttpWebRequest; webRequest.UserAgent = "CNBlogs";
本來以為HttpClient也有同樣的UserAgent屬性,於是想這樣寫:
var httpClient = new HttpClient(); httpClient.UserAgent = "CNBlogs";//錯誤的代碼
結果發現HttpClient根本沒有UserAgent這個屬性。
於是,找啊找,終於找到了一個UserAgent:
var httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.UserAgent
以為就是它了,卻發現這里的UserAgent是只讀屬性。
再一看它的類型是HttpHeaderValueCollection<ProductInfoHeaderValue>,可以Add,Add的參數類型是ProductInfoHeaderValue,於是new ProductInfoHeaderValue,構造函數的參數類型是ProductHeaderValue,於是new ProductHeaderValue。代碼如下:
var httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.UserAgent.Add( new ProductInfoHeaderValue( new ProductHeaderValue("CNBlogs")));
運行代碼一看,的確得到了想要的UserAgent。順藤摸瓜終於摸到了,但有些復雜。
換了根藤摸,摸到了一個稍微簡單些的瓜,這樣也可以:
var httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.UserAgent.Add( new ProductInfoHeaderValue("CNBlogs", null));
根據實際需求,需要在UserAgent中設置郵件地址,於是代碼改為:
var httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.UserAgent.Add( new ProductInfoHeaderValue( new ProductHeaderValue("contact@cnblogs.com")));
運行結果竟然報錯:
failed: System.FormatException : The format of value 'contact@cnblogs.com' is invalid.
at System.Net.Http.Headers.HeaderUtilities.CheckValidToken(String value, String parameterName)
at System.Net.Http.Headers.ProductHeaderValue..ctor(String name)
而在HttpWebRequest中是可以的:
var webRequest = WebRequest.Create(url) as HttpWebRequest; webRequest.UserAgent = "contact@cnblogs.com";
摸了半天,原來摸到的是半生不熟的瓜。。。
算了,還是求助摸瓜高手Google吧。。。找到了How to use HttpClient handlers中的一行代碼:
httpClient.DefaultRequestHeaders.Add("user-agent", "...");
高手一出手,就知有沒有,改為這個代碼就能搞定:
var httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.Add("UserAgent", "contact@cnblogs.com");
這個應該是HtppClient中設置UserAgent最簡單的方法,HttpWebRequest的對應實現是:
var webRequest = WebRequest.Create(url) as HttpWebRequest; webRequest.Headers.Add("UserAgent", "contact@cnblogs.com");
搞定是搞定了,原以為HttpClient會比HttpWebRequest更簡單。可是現在設置UserAgent這么簡單的操作,使用HttpWebRequest信手拈來,只要輸入“.u”,智能感知就能找到;使用HttpClient反而有些麻煩,不僅沒有智能感知,而且要手動輸入字符串"UserAgent"。
我想絕大多數人使用HttpClient設置UserAgent時,首先想到的是HttpClient.UserAgent。優秀的設計應該是用戶想到哪里,它就出現在哪里。而不“簡單”的HttpClient卻要和用戶捉迷藏。
HttpClient與HttpWebRequest究竟有什么區別,為什么要故意顯得與HttpWebRequest不一樣?
MSDN上是這么說:
By default, HttpWebRequest will be used to send requests to the server.
If an app using HttpClient and related classes in the System.Net.Http namespace intends to download large amounts of data (50 megabytes or more).
僅僅因為響應請求的數據量大,HttpClient就與HttpWebRequest差別如此大,這是站不住腳的理由。
后來在Henrik's Blog中找到這樣一句話:
The default HttpClient is the simplest way in which you can start sending requests. A single HttpClient can be used to send as many HTTP requests as you want concurrently so in many scenarios you can just create one HttpClient and then use that for all your requests.
原來答案在這里!HttpClient最與眾不同的地方是同一個HttpClient實例可以發出多次請求,每次請求是可以是完全不同的URL。而一個HttpWebRequest實例對應於一個Url的一次請求。這才是HttpClient與HttpWebRequest的最大區別所在。
本來寫這篇博客是想批評HttpClient,寫的過程中才發現原來是自己對HttpClient不夠了解。但是依然以批評收尾,HttpClient設計得不夠簡單。