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);          //结尾的标题
        }
    }
  • HttpHeadersHttpRequestHeadersHttpResponseHeaders 的基类。
  • 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处理程序。

处理程序管道

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第1章 进程、线程与网络协议  1.1 进程和线程  1.1.1 Process类  1.1.2 Thread类  1.1.3 在一个线程中操作另一个线程的控件 1.2 IP地址与端口  1.2.1 TCP/IP  1.2.2 IPAddress类与Dns类  1.2.3 IPHostEntry类  1.2.4 IPEndPoint类  1.3 套接字  1.3.1 Socket类  1.3.2 面向连接的套接字  1.3.3 无连接的套接字  1.4 网络流  习题  第2章 TCP应用编程  2.1 同步TCP应用编程  2.1.1 使用套接字发送和接收数据  2.1.2 使用NetworkStream对象发送和接收数据  2.1.3 TcpClient与TcpListener类  2.1.4 解决TCP的无消息边界问题  2.2 利用同步TCP编写网络游戏  2.2.1 服务器端编程  2.2.2 客户端编程  2.3 异步TCP应用编程  2.3.1 EventWaitHandle类  2.3.2 AsyncCallback委托  2.3.3 BeginAcceptTcpClient方法和EndAcceptTcpClient方法  2.3.4 BeginConnect方法和EndConnect方法  2.3.5 发送数据  2.3.6 接收数据  2.4 异步TCP聊天程序  2.4.1 服务器端设计  2.4.2 客户端设计  习题  第3章 UDP应用编程  3.1 UDP基础知识  3.2 UDP应用编程技术  3.2.1 UdpClient类  3.2.2 发送和接收数据的方法  3.3 利用UDP进行广播和组播  3.3.1 通过Internet实现群发功能  3.3.2 在Internet上举行网络会议讨论  习题  第4章 P2P应用编程  4.1 P2P基础知识  4.2 P2P应用举例  习题  第5章 SMTP与POP3应用编程  5.1 通过应用程序发送电子邮件  5.1.1 SMTP  5.1.2 发送邮件  5.2 利用同步TCP接收电子邮件  5.2.1 POP3工作原理  5.2.2 邮件接收处理  习题  第6章 网络数据加密与解密  6.1 对称加密  6.2 不对称加密  6.3 通过网络传递加密数据 6.4 Hash算法与数字签名  习题  第7章 三维设计与多媒体编程  7.1 简单的3D设计入门  7.2 DirectX基础知识  7.2.1 左手坐标系与右手坐标系  7.2.2 设备  7.2.3 顶点与顶点缓冲  7.2.4 Mesh对象  7.2.5 法线  7.2.6 纹理与纹理映射  7.2.7 世界矩阵、投影矩阵与视图矩阵  7.2.8 背面剔除  7.3 Primitive  7.4 Mesh  7.5 灯光与材质  7.6 音频与视频  7.7 直接使用SoundPlayer类播放WAV音频文件  习题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值