C# 学习笔记-使用 类型化客户端搭建HTTP客户端服务

文章目录

  • 一、概述
    • [1.1 框架语言](#1.1 框架语言)
    • [1.2 Http简介](#1.2 Http简介)
  • 二、使用IHttpClientFatory
    • [2.1 安装Nuget包](#2.1 安装Nuget包)
    • [2.2 类型化客户端](#2.2 类型化客户端)
      • [2.2.1 创建数据模型](#2.2.1 创建数据模型)
      • [2.2.2 创建服务类](#2.2.2 创建服务类)
      • [2.2.3 注册服务](#2.2.3 注册服务)
      • [2.2.4 应用代码中访问](#2.2.4 应用代码中访问)

香染衣

黑海森狱五大晶灵中最擅防御术的金晶灵,有着公子般的文质气息,外貌较为冷艳,性格却是十分豪爽,外冷内热、快人快语,与随从晴儿互动总是干净利落。隐居在森狱深处的天堂森林中,已许久不管森狱之事,但依旧暗中注意着森狱的变化,故当玄同与紫鷨因替阎王取药的关系,来到天堂森林,也开启了金晶灵再出的契机。

一、概述

1.1 框架语言

框架:.net 10.0

C#语言:14.0

1.2 Http简介

超文本传输协议(Hypertext Transfer Protocol,HTTP)是一个简单的请求-响应协议,它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。请求和响应消息的头以ASCII形式给出;而消息内容则具有一个类似MIME的格式。超文本传输协议是一种用于分布式、协作式和超媒体信息系统的应用层协议,是万维网WWW(World Wide Web)的数据通信的基础。

HTTP是应用层协议,同其他应用层协议一样,是为了实现某一类具体应用的协议,并由某一运行在用户空间的应用程序来实现其功能。HTTP是一种协议规范,这种规范记录在文档上,为真正通过HTTP进行通信的HTTP的实现程序。

HTTP是基于B/S架构进行通信的,而HTTP的服务器端实现程序有httpd、nginx等,其客户端的实现程序主要是Web浏览器,例如Firefox、Internet Explorer、Google Chrome、Safari、Opera等,此外,客户端的命令行工具还有elink、curl等。Web服务是基于TCP的,因此为了能够随时响应客户端的请求,Web服务器需要监听在80/TCP端口。这样客户端浏览器和Web服务器之间就可以通过HTTP进行通信了。

HTTP是基于客户/服务器模式,且面向连接的。典型的HTTP事务处理有如下的过程:

(1)客户与服务器建立连接;

(2)客户向服务器提出请求;

(3)服务器接受请求,并根据请求返回相应的文件作为应答;

(4)客户与服务器关闭连接。

二、使用IHttpClientFatory

2.1 安装Nuget包

  • Microsoft.Extensions.Http
  • Microsoft.Extensions.Hosting

我这边安装最新稳定版本:10.0.12

工具-> NuGet 包管理器 -> 管理解决方案的NuGet 程序包,然后搜索对应的包进行添加。

注: 本文数据使用https://jsonplaceholder.typicode.com/作为测试。

2.2 类型化客户端

2.2.1 创建数据模型

csharp 复制代码
    /// <summary>
    /// 待办
    /// </summary>
    /// <param name="UserId"></param>
    /// <param name="Id"></param>
    /// <param name="Title"></param>
    /// <param name="Completed"></param>
    public record class Todo(
        int UserId,
        int Id,
        string Title,
        bool Completed);

2.2.2 创建服务类

csharp 复制代码
    /// <summary>
    /// Todo服务
    /// </summary>
    /// <remarks>使用类型化客户端时是,需要有包含HttpClient的构造函数</remarks>
    public class TodoService(HttpClient httpClient)
    {
        public async Task<Todo[]> GetUserTodosAsync(int userId)
        {
            try
            {
                // Make HTTP GET request
                // Parse JSON response deserialize into Todo type
                Todo[]? todos = await httpClient.GetFromJsonAsync<Todo[]>(
                    $"todos?userId={userId}",
                    new JsonSerializerOptions(JsonSerializerDefaults.Web));

                return todos ?? [];
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error getting something fun to say: {Error}", ex.Message);
            }

            return [];
        }
    }

2.2.3 注册服务

在启动代码中进行注册。

csharp 复制代码
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        public static IServiceProvider Services { get; private set; } = null!;
        private HostApplicationBuilder builder = Host.CreateApplicationBuilder();

        protected override void OnStartup(StartupEventArgs e)
        {
            builder.Services.AddHttpClient<TodoService>()
                .ConfigureHttpClient(client =>
                {
                    // 设置地址
                    client.BaseAddress = new Uri("https://jsonplaceholder.typicode.com/");
                    // 设置客户端身份
                    client.DefaultRequestHeaders.UserAgent.ParseAdd("todo-client");
                });
					// 通过DI获取控件,才能正常注册,需要注销Xaml中的StartUri
            builder.Services.AddTransient<MainWindow>();
            var host = builder.Build();
            Services = host.Services;

            // 从容器解析主窗口并显示
            var mainWindow = Services.GetRequiredService<MainWindow>();
            mainWindow.Show();

            base.OnStartup(e);
        }

    }

2.2.4 应用代码中访问

csharp 复制代码
        private readonly TodoService? todoService;

        /// <summary>
        /// 客户端,需要实现有参构造函数才能正常使用
        /// </summary>
        /// <param name="todoService"></param>
        public MainWindow(TodoService todoService) : this()
        {
            this.todoService = todoService;
        }

        public MainWindow()
        {
            InitializeComponent();
        }



        private void Btn_GetTodos_Click(object sender, RoutedEventArgs e)
        {
            _ = GetTodo();
        }

        private async Task GetTodo()
        {
            if (todoService == null) return;
            var todos = await todoService.GetUserTodosAsync(1);
            for (int i = 0; i < todos.Length; i++)
            {
                WriteLog(todos[i].ToString());
            }
        }

        private void WriteLog(string msg)
        {
            paragraph_msg.Inlines.Add(new Run(msg));
            paragraph_msg.Inlines.Add(new LineBreak());
        }
    }
相关推荐
高亦真1 小时前
今天是学习嵌入式的第38天
linux·学习·算法
比兔代理2 小时前
代理 IP 延迟优化全链路:从节点选型、TCP 参数到协议栈调优
网络·http·ip
传奇开心果编程2 小时前
【Rust入门知识点学与练】第33课:异步编程入门(async/await)强化
开发语言·学习·rust
传奇开心果编程2 小时前
【Rust入门知识点学与练】第34课:所有权与借用
开发语言·学习·rust
AAA代码批发商2 小时前
DAY43 ARM 体系结构学习笔记|嵌入式入门,从硬件组件到流水线、内存与栈帧
arm开发·笔记·学习
彧azz2 小时前
初学Unity:编辑器
笔记·学习·unity·游戏引擎
明德扬3 小时前
AD9653单通道波形怎么看?幅度、频率与基础测量入门
学习·fpga开发·fpga
geovindu3 小时前
CSharp:Condition Variable Pattern
后端·设计模式·c#·.net·.netcore·条件变量模式·同步型模式
幼儿园蛋小黄3 小时前
学习ARM
学习