引言:API 并不可怕,反而非常方便
\n\n想象一下,你正在点一份披萨。你给餐厅打电话,告知地址和配料——30分钟后外卖员就送到门口了。编程中的 API 工作原理完全一样:它就像那个“电话呼叫”,通过它一个程序与另一个程序通信。只不过,这里用的是 HTTP 请求代替声音,数据代替披萨。
\n\n在 C# 开发的世界里,API 是基础。任何现代项目,无论是 Web 应用、移动后端还是企业级服务,都或多或少会“调用”外部服务。这时就出现了一个核心问题:应该选择哪种协议? REST、GraphQL 还是 gRPC?每种协议各有千秋,但每种都适用于不同的任务。
\n\n在本文中,我们将通过实际示例来探讨在 C# 中使用 API。你将学习如何发送 HTTP 请求,如何让 C# 与 GraphQL 和 gRPC 协同工作,最重要的是——你将明白何时该使用哪种技术。我们开始吧!
\n\n\n\n
1. C# 中的 REST API:永不褪色的经典
\n\nREST(表述性状态转移) 是一种架构风格,多年来一直是事实上的标准。它简单、直观,运行在 HTTP 之上。如果你曾经编写过发送 GET 或 POST 请求的代码,那么你已经使用过 REST 了。
\n\n如何在 C# 中发送 REST 请求
\n\n在 C# 中,处理 REST 最常用的是 HttpClient 类。它内置于 .NET 中,功能强大:从简单的 GET 请求到带有 JSON 主体的复杂 POST 请求,无所不能。
以下是向 REST API 发送典型请求的 C# 代码示例:
\n\nusing System;\nusing System.Net.Http;\nusing System.Threading.Tasks;\n\nclass Program\n{\n static async Task Main(string[] args)\n {\n using HttpClient client = new HttpClient();\n client.BaseAddress = new Uri("https://api.example.com/");\n \n HttpResponseMessage response = await client.GetAsync("users/1");\n if (response.IsSuccessStatusCode)\n {\n string json = await response.Content.ReadAsStringAsync();\n Console.WriteLine(json);\n }\n }\n}\n\n\n简洁明了。HttpClient 生命周期较长,因此通常只创建一次并重复使用(在实际项目中通过 DI 容器实现)。
何时选择 REST
\n- \n
- 你正在为 Web 或移动应用编写公共 API。 \n
- 客户端是浏览器、移动设备、物联网设备。 \n
- 你需要简单性和 HTTP 级别的缓存。 \n
REST 的缺点: 数据冗余(通常返回的数据比需要的多)以及 N+1 查询问题,即为了获取关联数据需要多次调用。
\n\n\n\n
2. C# 中的 GraphQL:只请求你需要的内容
\n\nGraphQL 是一种由 Facebook 创建的查询语言。它的主要特点是:客户端自己决定需要哪些字段。没有多余的信息,没有数十个端点——一次查询,一次响应。
\n\n从 C# 发送 GraphQL 请求
\n\n在 C# 中处理 GraphQL,可以直接使用 HttpClient,但更方便的是使用 GraphQL.Client 库(NuGet 包 GraphQL.Client)。
向 GraphQL API 发送请求的示例:
\n\nusing System;\nusing System.Threading.Tasks;\nusing GraphQL;\nusing GraphQL.Client.Http;\nusing GraphQL.Client.Serializer.Newtonsoft;\n\nclass Program\n{\n static async Task Main(string[] args)\n {\n using var client = new GraphQLHttpClient("https://api.example.com/graphql", new NewtonsoftJsonSerializer());\n\n var request = new GraphQLRequest\n {\n Query = @"\n {\n user(id: 1) {\n name\n email\n posts {\n title\n }\n }\n }"\n };\n\n var response = await client.SendQueryAsync<dynamic