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处理程序。

处理程序管道
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,591评论 18 139
  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 10,857评论 6 13
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,565评论 18 399
  • 每天一个小时喝茶聊事的时间已经成为一种习惯。 今天我煮了白茶。 今天的分享与白茶有关,意境在煮茶时。 从开始接触白...
    So大江哥阅读 491评论 0 0
  • (by孤坐未央) 我在千里冰封的山上坐着 一挥手碰倒了南方的月光 于是你那里的天空熠熠发亮 我曾告诉你 我拥有一座...
    那时我就应该离开才对阅读 213评论 0 1