1.異步調(diào)用 Web 服務(wù)
static void Main(string[] args)
{
Console.WriteLine("In main before call to GetData!");
GetData();
Console.WriteLine("Back in main after call to GetData!");
Console.ReadKey();
}
private static async void GetData()
{
HttpClient httpClient = new HttpClient();
HttpResponseMessage response = null;
response = await httpClient.GetAsync("http://services.odata.org/Northwind/Northwind.svc/Regions");
if (response.IsSuccessStatusCode)
{
Console.WriteLine("Response Status Code and Reason Phrase: " + response.StatusCode + " " + response.ReasonPhrase);
string responseBodyAsText = response.Content.ReadAsStringAsync().Result;
Console.WriteLine("Received payload of " + responseBodyAsText.Length + " characters");
//Console.WriteLine(responseBodyAsText);
}
}
來看看下面方法解釋:
因為 HttpClient 使用 GetAsync 方法調(diào)用荤牍,且使用了 await,所以 Main 方法輸出到屏幕的消息先顯示棺禾,而 GetData
調(diào)用中的數(shù)據(jù)后顯示。
對 GetAsync 返回一個 HttpResponseMessage
對象。表示包含的標(biāo)題、狀態(tài)和內(nèi)容的響應(yīng)咙冗。檢查響應(yīng)的 IsSuccessStatusCode
屬性,可以確定請求是否成功漂彤。
2.標(biāo)題
HttpClient 的 DefaultRequestHeaders
屬性允許設(shè)置或改變標(biāo)題雾消。使用 Add
可以給集合添加標(biāo)題。下面意義相同挫望。
//httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
標(biāo)題和標(biāo)題值會與這個 HttpClient 實例發(fā)送的每個請求一起發(fā)送仪或。
下面的例子說明了如何在響應(yīng)和請求中遍歷標(biāo)題。
static void Main(string[] args)
{
GetData();
Console.ReadKey();
}
private static void GetData()
{
HttpClient httpClient = new HttpClient();
HttpResponseMessage response = null;
httpClient.DefaultRequestHeaders.Add("Accept", "application/json;odata=verbose");
Console.WriteLine("Request Headers:");
//請求的標(biāo)題
EnumerateHeaders(httpClient.DefaultRequestHeaders);
Console.WriteLine();
response = httpClient.GetAsync("http://services.odata.org/Northwind/Northwind.svc/Regions").Result;
if (response.IsSuccessStatusCode)
{
Console.WriteLine("Response Headers:");
EnumerateHeaders(response.Headers); //結(jié)尾的標(biāo)題
}
}
-
HttpHeaders
是HttpRequestHeaders
和HttpResponseHeaders
的基類士骤。 -
HttpHeaders
對象定義的為KeyValuePair<string, IEnumerable<string>>
。這表示每個標(biāo)題在集合中都可以有多個值蕾域。因此要改變標(biāo)題中的值拷肌,就需要先刪除原來的值,添加新值旨巷。
private static void EnumerateHeaders(HttpHeaders headers)
{
foreach (var header in headers)
{
var value = "";
foreach (var val in header.Value)
{
value = val + " ";
}
Console.WriteLine("Header: " + header.Key + " Value: " + value);
}
}
因為標(biāo)題值可以有多個巨缘,標(biāo)題值部分也必須迭代,所以在循環(huán)內(nèi)部還有一個循環(huán)采呐,來枚舉所有找到的值若锁。
3.HttpContent
響應(yīng)中的 Content
屬性返回一個 HttpContent
對象。例子中使用 ReadAsStringAsync
返回內(nèi)容的字符串表示斧吐。顧名思義又固,這是一個異步調(diào)用仲器,但這個例子沒使用異步調(diào)用功能。調(diào)用 Result 會阻塞該調(diào)用仰冠,直到 ReadAsStringAsync 方法執(zhí)行完畢乏冀。
var client = new HttpClient();
//GetAsync 方法也接受一個 CancellationToken
HttpResponseMessage response = await client.GetAsync("http://www.baidu.com");
response.EnsureSuccessStatusCode();
string html = await response.Content.ReadAsStringAsync();
Console.WriteLine(html);
其他從 HttpContent
對象獲取數(shù)據(jù)的方法有 ReadAsByteArrayAsync
(返回數(shù)據(jù)的字節(jié)數(shù)組)和 ReadAsStreamAsync
(返回一個流)。也可以使用 LoadIntoBufferAsync
把內(nèi)容加載到內(nèi)存緩存中洋只。
Headers
屬性返回 HttpCotentHeaders
對象辆沦。它工作方式與前面例子的請求和響應(yīng)標(biāo)題相同。
4.HttpMessageHandler
- 作為 HttpClient 構(gòu)造函數(shù)的參數(shù)识虚,就可以定制請求肢扯。
- 默認(rèn)使用
WebRequestHandler
對象。 - 有許多屬性可以設(shè)置 ClientCertificates担锤、Pipelining蔚晨、CachePolity、ImpersonationLevel 等妻献。
class Program
{
static void Main(string[] args)
{
GetData();
Console.ReadKey();
}
private static void GetData()
{
HttpClient httpClient = new HttpClient(new MessageHandler("error"));
HttpResponseMessage response = null;
Console.WriteLine();
response = httpClient.GetAsync("http://services.odata.org/Northwind/Northwind.svc/Regions").Result;
Console.WriteLine(response.StatusCode);
}
}
public class MessageHandler : HttpClientHandler //HttpClientHandler 繼承自 HttpMessageHandler
{
string displayMessage = "";
public MessageHandler(string message)
{
displayMessage = message;
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
Console.WriteLine("In DisplayMessageHandler " + displayMessage);
if (displayMessage == "error")
{
var response = new HttpResponseMessage(System.Net.HttpStatusCode.BadRequest); //創(chuàng)建要返回的響應(yīng) 把狀態(tài)設(shè)置為 BadRequest
var tsc = new TaskCompletionSource<HttpResponseMessage>();
tsc.SetResult(response); //注意響應(yīng)在 HttpResponseMessage 任務(wù)中 SetResult 方法設(shè)置
return tsc.Task;
}
return base.SendAsync(request, cancellationToken);
}
}
檢查 displayMessage 蛛株,是否為“error”。如果是育拨,就創(chuàng)建要返回的響應(yīng)谨履,把狀態(tài)設(shè)為 BadRequest
。接下來只創(chuàng)建了要返回的 Task
熬丧。注意響應(yīng)在 HttpResponseMessage
任務(wù)中通過 SetResult
方法設(shè)置笋粟。
添加定制處理器程序有很多理由。設(shè)置處理程序管道析蝴,是為添加多個處理程序害捕。除了默認(rèn)的處理程序外,還有 DelegatingHandler
闷畸,它執(zhí)行一些代碼尝盼,再把調(diào)用委托給內(nèi)部或下一個處理程序。 HttpClientHandler
是最后一個處理程序佑菩,它把請求發(fā)送到地址盾沫。
每個添加的 DelegatingHandler
都調(diào)用下一個或內(nèi)部的處理程序谅年,最后一個是基于 HttpClientHandler
處理程序摩桶。