Что такое HttpClient и как правильно с ним работать?
HttpClient — это класс из пространства имён System.Net.Http в .NET, предназначенный для отправки HTTP-запросов и получения HTTP-ответов от ресурса, идентифицируемого URI. Это основной инструмент для взаимодействия с внешними веб-сервисами и REST API в приложениях Xamarin и Xamarin.Forms. Он позволяет выполнять GET, POST, PUT, DELETE и другие запросы, отправлять данные, загружать файлы, а также управлять заголовками и куки.
Основные особенности HttpClient
-
Поддерживает асинхронное выполнение запросов через async/await.
-
Позволяет повторно использовать соединения, если используется правильно.
-
Имеет поддержку тайм-аутов, заголовков, аутентификации и проксирования.
-
Является кроссплатформенным — работает на Android, iOS, Windows и других платформах.
Создание экземпляра HttpClient
HttpClient httpClient = new HttpClient();
Чтобы задать базовый адрес:
httpClient.BaseAddress = new Uri("https://api.example.com/");
Выполнение HTTP-запросов
GET-запрос:
var response = await httpClient.GetAsync("users/1");
POST-запрос:
var json = JsonConvert.SerializeObject(newUser);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await httpClient.PostAsync("users", content);
PUT-запрос:
var json = JsonConvert.SerializeObject(updatedUser);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await httpClient.PutAsync("users/1", content);
DELETE-запрос:
var response = await httpClient.DeleteAsync("users/1");
Чтение ответа
if (response.IsSuccessStatusCode)
{
var responseContent = await response.Content.ReadAsStringAsync();
var user = JsonConvert.DeserializeObject<User>(responseContent);
}
else
{
Debug.WriteLine($"Ошибка: {response.StatusCode}");
}
Добавление заголовков
httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "your_token");
httpClient.DefaultRequestHeaders.Add("Custom-Header", "value");
Обработка ошибок
try
{
var response = await httpClient.GetAsync("users");
response.EnsureSuccessStatusCode(); // выбрасывает исключение, если код != 2xx
var json = await response.Content.ReadAsStringAsync();
var users = JsonConvert.DeserializeObject<List<User>>(json);
}
catch (HttpRequestException ex)
{
Debug.WriteLine($"Ошибка HTTP: {ex.Message}");
}
catch (Exception ex)
{
Debug.WriteLine($"Общая ошибка: {ex.Message}");
}
Тайм-аут запроса
httpClient.Timeout = TimeSpan.FromSeconds(30);
Можно также использовать CancellationToken:
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
var response = await httpClient.GetAsync("users", cts.Token);
Переиспользование HttpClient
Очень важно не создавать новый HttpClient при каждом запросе. Это может привести к исчерпанию сокетов и утечкам памяти. Рекомендуется:
-
Использовать Singleton-паттерн
-
Или внедрять через **Dependency Injection
** - Или использовать HttpClientFactory (в MAUI/.NET Core)
Пример Singleton:
public static class HttpClientProvider
{
private static HttpClient \_client;
public static HttpClient Client => \_client ??= CreateClient();
private static HttpClient CreateClient()
{
var client = new HttpClient();
client.BaseAddress = new Uri("https://api.example.com/");
return client;
}
}
Использование:
var response = await HttpClientProvider.Client.GetAsync("users");
HttpMessageHandler и делегаты
Можно использовать делегирующие обработчики для логирования, подмены заголовков, ретраев:
public class LoggingHandler : DelegatingHandler
{
public LoggingHandler(HttpMessageHandler innerHandler) : base(innerHandler) { }
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
Debug.WriteLine($"Запрос: {request.Method} {request.RequestUri}");
var response = await base.SendAsync(request, cancellationToken);
Debug.WriteLine($"Ответ: {response.StatusCode}");
return response;
}
}
Подключение:
var client = new HttpClient(new LoggingHandler(new HttpClientHandler()));
Отправка форм (multipart/form-data)
Для загрузки файлов или форм:
var form = new MultipartFormDataContent();
var fileContent = new ByteArrayContent(fileBytes);
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("image/jpeg");
form.Add(fileContent, "file", "photo.jpg");
form.Add(new StringContent("myuser"), "username");
var response = await httpClient.PostAsync("upload", form);
Работа с куками
HttpClient сам по себе не сохраняет куки. Для этого используйте HttpClientHandler с включённой поддержкой CookieContainer:
var cookieContainer = new CookieContainer();
var handler = new HttpClientHandler { CookieContainer = cookieContainer };
var client = new HttpClient(handler);
Использование System.Text.Json вместо Newtonsoft
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
var user = JsonSerializer.Deserialize<User>(jsonString, options);
Отладка и логирование
-
Используйте Fiddler, Charles Proxy, Wireshark или встроенные обработчики (HttpMessageHandler) для анализа трафика.
-
Debug.WriteLine(response.RequestMessage.ToString()) позволяет видеть отправляемые заголовки.
Сетевые ограничения на мобильных устройствах
Убедитесь, что в AndroidManifest.xml добавлены разрешения:
```python
<uses-permission android:name="android.permission.INTERNET" />
На iOS начиная с iOS 9 нужно разрешить небезопасные соединения (HTTP) в Info.plist, если используется не HTTPS:
<br/>```python
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
Распространённые ошибки
Ошибка | Причина |
---|---|
TaskCanceledException | Тайм-аут запроса или CancellationToken отменил запрос |
--- | --- |
HttpRequestException | Сетевая ошибка или неправильный адрес |
--- | --- |
SocketException: No such host is known | DNS-ошибка, нет интернета или опечатка в URI |
--- | --- |
500 Internal Server Error | Проблема на сервере API |
--- | --- |
HttpClient — мощный инструмент, но его правильное использование требует понимания принципов работы HTTP, управления временем жизни объекта, обработки ошибок и асинхронного программирования. В Xamarin этот класс широко используется для создания REST-клиентов, авторизации, загрузки медиа, синхронизации данных и других задач.