.Net HttpClient 处理响应数据

HttpClient 处理响应数据

1、初始化及全局设置

csharp 复制代码
//初始化:必须先执行一次
#!import ./ini.ipynb

2、处理响应状态

csharp 复制代码
//判断响应码:正常
{
    var response = await SharedClient.GetAsync("api/Normal/GetAccount?id=1");
    if(response.StatusCode == System.Net.HttpStatusCode.OK)
    {
        var content = await response.Content.ReadAsStringAsync();
        Console.WriteLine($"响应码正常:{content}");
    }
}

//判断响应码:非正常
{
    var response = await SharedClient.GetAsync("api/Normal/GetAccount?id=b");
    if(response.StatusCode != System.Net.HttpStatusCode.OK)
    {
        Console.WriteLine($"响应码异常:状态码 {response.StatusCode}");
    }
}

//确保正确响应:正常
{
    var response = await SharedClient.GetAsync("api/Normal/GetAccount?id=1");

    //确保异常
    response.EnsureSuccessStatusCode();

    var result = await response.Content.ReadFromJsonAsync<BaseResult<Account>>();
    //result.Display();
    Console.WriteLine($"响应正常:内容为 {result}");
}

//确保正确响应:异常
{
    try 
    {
        var response = await SharedClient.GetAsync("api/Normal/GetAccount?id=c");
        
        //确保异常
        response.EnsureSuccessStatusCode();
        //result.Display();

        var result = await response.Content.ReadFromJsonAsync<BaseResult<Account>>();
        Console.WriteLine($"响应正常:内容为 {result}");
    }
    catch(Exception e)
    {
        Console.WriteLine($"请求异常:{e.Message}");
    } 
}

//使用 ry catch 捕获所有异常
{
    try 
    {
        var result = await SharedClient.GetFromJsonAsync<BaseResult<Account>>("api/Normal/GetAccount?id=a");
        //result.Display();
        Console.WriteLine($"响应正常:内容为 {result}");
    }
    catch(Exception e)
    {
        Console.WriteLine($"请求异常:{e.Message}");
    }
    finally
    {
        //收发业务
    }
}

3、处理异常响应

3.1 try catch

csharp 复制代码
//try catch 常规异常处理
{
    try 
    {
        var response = await SharedClient.GetAsync("api/Normal/GetAccount?id=c");
        
        //确保异常
        response.EnsureSuccessStatusCode();

        var result = await response.Content.ReadFromJsonAsync<BaseResult<Account>>();
        Console.WriteLine($"响应正常:内容为 {result}");
    }
    catch(Exception e)
    {
        Console.WriteLine($"接口异常:{e.Message}");
    }
    finally
    {
        //清理
    }
}

3.2 管道统一处理

csharp 复制代码
//异常处理管理中间件
public class ExceptionDelegatingHandler : DelegatingHandler 
{
    protected override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        Console.WriteLine("ExceptionDelegatingHandler -> Send -> Added Token");

        HttpResponseMessage response = new HttpResponseMessage(System.Net.HttpStatusCode.InternalServerError);
        try 
        {
            response = base.Send(request, cancellationToken);
            response.EnsureSuccessStatusCode();
        }
        catch(Exception ex)
        {
            //统一异常处理,当然也可以分类别处理
            Console.WriteLine($"中间件中,接口调用异常:{ex.Message}");
        }
        finally
        {
            Console.WriteLine("ExceptionDelegatingHandler -> Send -> After");
        }

        return response;
    }

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        Console.WriteLine("ExceptionDelegatingHandler -> SendAsync -> Before");

        HttpResponseMessage response = new HttpResponseMessage(System.Net.HttpStatusCode.InternalServerError);
        try 
        {
            response = await base.SendAsync(request, cancellationToken);
            //可以根据状态码,分别进行处理
            response.EnsureSuccessStatusCode();
        }
        catch(Exception ex)
        {
            //统一异常处理,当然也可以分类别处理
            //可以重试等操作
            Console.WriteLine($"中间件中,接口调用异常:{ex.Message}");
        }
        finally
        {
            Console.WriteLine("ExceptionDelegatingHandler -> Send -> After");
        }

        return response;
    }
}

//使用异常管道,发送请求
{
    //使用管道中间件,统一处理
    ExceptionDelegatingHandler exceptionHandler = new ExceptionDelegatingHandler()
    {
        InnerHandler = new  SocketsHttpHandler()
    };

    HttpClient clientWithExceptionHandler = new HttpClient(exceptionHandler)
    {
        BaseAddress = new Uri(webApiBaseUrl),
    };

    //发送请求
    var response = await clientWithExceptionHandler.GetAsync("api/Normal/GetAccount?id=c");
    if(response.StatusCode == System.Net.HttpStatusCode.OK)
    {
        var result = await response.Content.ReadFromJsonAsync<BaseResult<Account>>();
        Console.WriteLine($"响应正常:内容为 {result}");
    }
    else
    {
         Console.WriteLine($"接口异常:状态码 {response.StatusCode}");
    }
}

3.3 类型化客户端统一处理

csharp 复制代码
//类型化客户端
public class HelloApiService 
{
    public HttpClient Client { get; set; }

    public HelloApiService(HttpClient httpClient)
    {
        Client = httpClient;
    }

    //处理异常:也可以结合AOP,进行统一拦截处理
    public async Task<string> Ping()
    {
        try 
        {
            var content = await Client.GetStringAsync("/api/Hello/Ping2");
            return content;
        }
        catch(Exception ex)
        {
            return $"远程调用异常:{ex.Message}";
        }
    }
}

//使用
{
    //注册类型化客户端
    var services = new ServiceCollection();
    services.AddHttpClient<HelloApiService>(client => 
    {
        client.BaseAddress = new Uri(webApiBaseUrl);
    })
    .ConfigureHttpClient(client=>
    {
        client.Timeout = TimeSpan.FromSeconds(1);
    });
    
    //使用类型化客户端,进行远程调用
    var apiService = services.BuildServiceProvider().GetService<HelloApiService>();
    var s = await apiService.Ping();
    Console.WriteLine(s);
}

3.4 Polly库(重试、降级、熔断等,可结合类型化客户端和工厂模式)

csharp 复制代码
//Polly进行异常处理
var services = new ServiceCollection();
services.AddHttpClient(string.Empty)
    //配置默认命名客户端
    .ConfigureHttpClient(client => 
    {
        client.BaseAddress = new Uri(webApiBaseUrl);
    })
    //设置Policy错误处理快捷扩展方法
    .AddTransientHttpErrorPolicy(builder => builder.WaitAndRetryAsync
    (
        new[]
        {
            TimeSpan.FromSeconds(1),
            TimeSpan.FromSeconds(2),
            TimeSpan.FromSeconds(4),
        }
    ))
    //可以多次调用:设置多个策略
    .AddTransientHttpErrorPolicy(builder => builder.RetryAsync(1));

var factory = services.BuildServiceProvider().GetService<IHttpClientFactory>();
var content = await factory.CreateClient().GetStringAsync("/api/polly8/RandomException");
Console.WriteLine($"响应内容:{content}");

4、处理响应数据

4.1 接收响应头数据

csharp 复制代码
//响应头信息
{
    var response = await SharedClient.GetAsync("api/Normal/GetAccount?id=1");

    Console.WriteLine("响应头:");
    foreach(var header in response.Headers)
    {
        var headerValues = string.Join(",", header.Value);
        Console.WriteLine($"{header.Key} = {headerValues}");
    }
}

4.2 接收响应体数据

csharp 复制代码
//响应体数据(json为例)
{
    var response = await SharedClient.GetAsync("api/Normal/GetAccount?id=1");
    //获取响应体内容
    var content = await response.Content.ReadAsStringAsync();
    Console.WriteLine($"响应体数据:{content}"); 
}
相关推荐
ChaITSimpleLove11 小时前
.NET 10 的 AI 技术栈全景:M.E.AI、MCP 与 Agent Framework 深度解析
人工智能·.net·ai agent·mcp·agent framework·m.e.ai·hosted agents
格林威14 小时前
C# 相机Burst模式图像采集:使用相机内存配合OpenCvSharp和Halcon实现短时间的高速采集的方法
开发语言·人工智能·数码相机·计算机视觉·c#·视觉检测·工业相机
J总裁的小芒果15 小时前
参数过多-分批传参
c#
典典分享指南16 小时前
短视频分镜提示词:让 AI 出片的产品口播
java·c#·bash·composer·symfony
Z59981784117 小时前
c#软件开发学习笔记--WPF(Canvas、数据绑定、MVVM模式、值转换器)
笔记·学习·c#
数据知道18 小时前
.NET 反序列化漏洞——ViewState 与 BinaryFormatter 实战深度剖析
网络·网络安全·.net
淡海水18 小时前
05-03-栈队列-PriorityQueue-TElement-TPriority-NET6优先队列语义与四叉堆实现
服务器·前端·c#·priorityqueue·clr·telement
leonkay1 天前
C# 特性(Attribute)——【1】基础讲解
开发语言·青少年编程·面试·c#·.net·个人开发
界面开发小八哥1 天前
界面控件DevExpress WinForms中文帮助文档 - 将基于DevExpress的.NET Framework应用迁移至最新版.NET
ui·.net·界面控件·winform·devexpress·ui开发
CSDN_RTKLIB1 天前
数据库七大符号表
c#