c# 如何调用 rest api

来源:这里教程网 时间:2026-02-21 17:38:17 作者:

HttpClient
发起 GET 请求最稳妥

直接 new

HttpClient
是常见错误起点——它本应复用,而非每次请求都新建。长期运行的服务若频繁创建销毁,会耗尽 socket 连接,触发
SocketException
HttpRequestException: Connection refused
。推荐将
HttpClient
声明为静态字段或通过 DI 注册为单例。

基础 GET 示例:

var client = new HttpClient();
var response = await client.GetAsync("https://api.example.com/users");
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
EnsureSuccessStatusCode()
会抛出异常(如 404/500),避免手动检查
response.IsSuccessStatusCode
若需设置超时,用
client.Timeout = TimeSpan.FromSeconds(10);
,别在
GetAsync
外套
Task.Wait()
Task.Result
GET 参数建议用
Uri.EscapeDataString()
手动拼接,或借助
FormUrlEncodedContent
+
PostAsync
模拟(不推荐);更安全的是用
HttpClient.BaseAddress
string.Concat()
构建完整 URI

POST JSON 数据必须设对
Content-Type

发 JSON 到 REST API 时,漏设

Content-Type: application/json
是 400 Bad Request 的头号原因。.NET 6+ 可用
JsonSerializer.SerializeToUtf8Bytes()
避免字符串编码开销;老版本建议用
StringContent
并显式指定编码。

示例(兼容 .NET 5+):

var client = new HttpClient();
var data = new { name = "Alice", email = "a@example.com" };
var json = JsonSerializer.Serialize(data);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync("https://api.example.com/users", content);
不要用
content.Headers.ContentType = new MediaTypeHeaderValue(...)
覆盖
StringContent
构造时已设的类型
若 API 要求
application/json; charset=utf-8
StringContent
默认已包含,无需额外处理
大对象 POST 建议用
StreamContent
+
FileStream
流式上传,避免内存峰值

带认证的请求要小心 header 注入时机

Bearer Token、API Key 等认证信息必须在发起请求前写入

client.DefaultRequestHeaders
,而不是每次调用
PostAsync
时临时加——后者在并发场景下可能被覆盖或遗漏。

Token 过期需刷新?别在
DefaultRequestHeaders.Authorization
里硬编码,改用
DelegatingHandler
拦截重试逻辑
Basic Auth 推荐用
Convert.ToBase64String(Encoding.ASCII.GetBytes($"{user}:{pass}"))
生成 credential,再设为
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", base64)
某些 API(如 GitHub)要求
User-Agent
header,漏掉会返回 403;可统一加:
client.DefaultRequestHeaders.UserAgent.ParseAdd("myapp/1.0")

错误处理不能只靠 try-catch

HttpRequestException
只覆盖网络层失败(DNS 错、连接断),但 HTTP 状态码如 401、422、503 会进到
response.IsSuccessStatusCode == false
分支。忽略这点,会导致业务逻辑把错误响应当成功数据解析。

统一检查
response.StatusCode
:401 走登录刷新,422 解析
response.Content
提取
errors
字段,503 可考虑指数退避重试
反序列化前务必确认
response.Content.Headers.ContentType?.MediaType == "application/json"
,否则
JsonSerializer.Deserialize<t>()</t>
可能抛
JsonException
日志中记录
response.RequestMessage?.RequestUri
response.StatusCode
,但切勿打
response.Content.ReadAsStringAsync()
的原始响应体(含敏感数据或超大 payload)
实际集成时,最难缠的是第三方 API 文档写得模糊:比如声称“返回 JSON”,实际空 body 时没设
Content-Type
;或要求
PUT
但实现只认
PATCH
。这些没法靠通用封装解决,得留一两个裸
HttpClient.SendAsync()
调用点,方便快速验证 raw request/response。

相关推荐