英文:
C# HttpClient and API
问题
- HttpClient类用于从API获取数据是否是最佳选择?我从API获取一个字符串然后将其反序列化为对象。
- 每次使用HttpClient都会创建一个新实例(每个用户都会创建)。最佳做法是每个请求都使用
using (HttpClient client = new HttpClient())
吗?
尝试找到最佳和最优解决方案。
英文:
I have a web application that pulls data from an API using the HttpClient class. I have a few questions.
- Is HttpClient optimal for getting data from API? I get a string from APi and deserialize it into an object.
- A new instance of HttpClient is created each time it is used (for each user). Is it best to use:
using (HttpClient client = new HttpClient())
for each request?
Try to find best and optimal solution.
答案1
得分: 5
-
是的,
HttpClient
绝对适用于使用 Web API 和反序列化。 -
对于每个请求都创建一个新的
HttpClient
不是一个好的用法。推荐的方式是使用IHttpClientFactory
接口创建HttpClient
对象。 以下是来自 MSDN 的基本用法示例:
class TodoService
{
private readonly IHttpClientFactory _httpClientFactory = null!;
private readonly ILogger<TodoService> _logger = null!;
public TodoService(
IHttpClientFactory httpClientFactory,
ILogger<TodoService> logger) =>
(_httpClientFactory, _logger) = (httpClientFactory, logger);
public async Task<Todo[]> GetUserTodosAsync(int userId)
{
// 创建客户端
using HttpClient client = _httpClientFactory.CreateClient();
try
{
// 发送 HTTP GET 请求
// 解析 JSON 响应并反序列化为 Todo 类型
Todo[]? todos = await client.GetFromJsonAsync<Todo[]>(
$"https://jsonplaceholder.typicode.com/todos?userId={userId}",
new JsonSerializerOptions(JsonSerializerDefaults.Web));
return todos ?? Array.Empty<Todo>();
}
catch (Exception ex)
{
_logger.LogError("获取有趣信息时发生错误:{Error}", ex);
}
return Array.Empty<Todo>();
}
}
你可以参考以下链接了解更多信息:
IHttpClientFactory with .NET
以及
HttpClient 使用指南
英文:
-
Yes,
HttpClient
is certainly appropriate for using web APIs and deserialization. -
Creating a new
HttpClient
for each request is not a good usage. The recommended way is to createHttpClient
objects using theIHttpClientFactory
interface. Here is a basic usage from MSDN:class TodoService { private readonly IHttpClientFactory _httpClientFactory = null!; private readonly ILogger<TodoService> _logger = null!; public TodoService( IHttpClientFactory httpClientFactory, ILogger<TodoService> logger) => (_httpClientFactory, _logger) = (httpClientFactory, logger); public async Task<Todo[]> GetUserTodosAsync(int userId) { // Create the client using HttpClient client = _httpClientFactory.CreateClient(); try { // Make HTTP GET request // Parse JSON response deserialize into Todo types Todo[]? todos = await client.GetFromJsonAsync<Todo[]>( $"https://jsonplaceholder.typicode.com/todos?userId={userId}", new JsonSerializerOptions(JsonSerializerDefaults.Web)); return todos ?? Array.Empty<Todo>(); } catch (Exception ex) { _logger.LogError("Error getting something fun to say: {Error}", ex); } return Array.Empty<Todo>(); } }
}
You can refer to
IHttpClientFactory with .NET
and
Guidelines for using HttpClient
答案2
得分: 2
-
可以设置HTTP标头来压缩数据,以优化有效载荷大小,假设有gzip/brotli可用。
-
HttpClient
不应每次都实例化,而是设计为单例。每个实例在操作系统级别打开套接字。一旦.NET处理完实例,需要一点时间才能完全关闭套接字,因此创建太多实例可能会导致通过HttpClient进行HTTP请求时对服务器造成拥塞。
英文:
-
Yes, you can also set HTTP headers to compress the data to optimize payload size assuming gzip/brotli are available.
-
The
HttpClient
is not meant to be instantiated per use. But, it is designed to be a singleton. Every instance opens up sockets at the OS level. Once .NET disposes of the instance it takes a bit for sockets to completely close so creating too many instances can choke the server making HTTP requests via HttpClient.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论