HttpClient 详解一《C#高级编程(第9版)》

1.异步调用 Web 服务

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 方法调用,且使用了 await,所以 Main 方法输出到屏幕的消息先显示,而 GetData 调用中的数据后显示。

对 GetAsync 返回一个 HttpResponseMessage 对象。表示包含的标题、状态和内容的响应。检查响应的 IsSuccessStatusCode 属性,可以确定请求是否成功。

2.标题

HttpClient 的 DefaultRequestHeaders 属性允许设置或改变标题。使用 Add 可以给集合添加标题。下面意义相同。

//httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

标题和标题值会与这个 HttpClient 实例发送的每个请求一起发送。

下面的例子说明了如何在响应和请求中遍历标题。

    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:");
        //请求的标题
        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);          //结尾的标题
        }
    }
  • HttpHeaders 是 HttpRequestHeaders 和 HttpResponseHeaders 的基类。
  • HttpHeaders对象定义的为 KeyValuePair<string, IEnumerable<string>>。这表示每个标题在集合中都可以有多个值。因此要改变标题中的值,就需要先删除原来的值,添加新值。
    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);
        }
    }

因为标题值可以有多个,标题值部分也必须迭代,所以在循环内部还有一个循环,来枚举所有找到的值。

效果

3.HttpContent

响应中的 Content 属性返回一个 HttpContent 对象。例子中使用 ReadAsStringAsync 返回内容的字符串表示。顾名思义,这是一个异步调用,但这个例子没使用异步调用功能。调用 Result 会阻塞该调用,直到 ReadAsStringAsync 方法执行完毕。

    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 对象获取数据的方法有 ReadAsByteArrayAsync(返回数据的字节数组)和 ReadAsStreamAsync(返回一个流)。也可以使用 LoadIntoBufferAsync 把内容加载到内存缓存中。

Headers 属性返回 HttpCotentHeaders 对象。它工作方式与前面例子的请求和响应标题相同。

4.HttpMessageHandler

  • 作为 HttpClient 构造函数的参数,就可以定制请求。
  • 默认使用 WebRequestHandler 对象。
  • 有许多属性可以设置 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);  //创建要返回的响应 把状态设置为  BadRequest
                var tsc = new TaskCompletionSource<HttpResponseMessage>();
                tsc.SetResult(response);       //注意响应在 HttpResponseMessage 任务中 SetResult 方法设置
                return tsc.Task;
            }
            return base.SendAsync(request, cancellationToken);
        }
    }

检查 displayMessage ,是否为“error”。如果是,就创建要返回的响应,把状态设为 BadRequest。接下来只创建了要返回的 Task。注意响应在 HttpResponseMessage 任务中通过 SetResult 方法设置。

添加定制处理器程序有很多理由。设置处理程序管道,是为添加多个处理程序。除了默认的处理程序外,还有 DelegatingHandler,它执行一些代码,再把调用委托给内部或下一个处理程序。 HttpClientHandler 是最后一个处理程序,它把请求发送到地址。
每个添加的 DelegatingHandler都调用下一个或内部的处理程序,最后一个是基于 HttpClientHandler处理程序。

处理程序管道

http://www.cnblogs.com/tangge/p/7082871.html

原文地址:https://www.cnblogs.com/cmblogs/p/9155968.html