HttpClient позволяет отправлять на сервер некоторые данные. Отправляемые данные представляют объект System.Net.Http.HttpContent. Но поскольку этот класс абстрактный то в реальности для отправки используется один из унаследованных классов. В частности, в .NET есть следующие встроенные классы, унаследованные от HttpContent:
System.Net.Http.ByteArrayContent: для отправки массива байтов
System.Net.Http.FormUrlEncodedContent: для отправки данных, закодированных с помощью типа MIME "application/x-www-form-urlencoded". (унаследован от ByteArrayContent)
System.Net.Http.StringContent: для отправки текста (унаследован от ByteArrayContent)
System.Net.Http.Json.JsonContent: для отправки json
System.Net.Http.MultipartContent: для отправки файлов
System.Net.Http.MultipartFormDataContent: для отправки файлов (унаследован от MultipartContent)
System.Net.Http.ReadOnlyMemoryContent: в качестве отправляемого содержимого используется ReadOnlyMemory<T>
System.Net.Http.StreamContent: отправляет поток Stream
В зависимости от задач и конкретного сервера, с которым мы взаимодействуем, мы можем применять один из этих типов.
Обычно данные отправляются с помощью запросов типа Post/Put/Patch. У HttpClient для отправки данных можно применять метод SendAsync() - в качестве параметра он принимает объект HttpRequestMessage, у которого через свойство Content
можно установить отправляемое содержимое.
Однако для упрощения отправки запросов HttpClient также предоставляет методы для каждого типа запроса:
PostAsync()
PutAsync()
PatchAsync()
Все эти методы принимают как минимум два параметра: адрес ресурса и отправляемые данные в виде объекта HttpContent?
:
Task<HttpResponseMessage> PostAsync (string? requestUri, System.Net.Http.HttpContent? content); Task<HttpResponseMessage> PutAsync (string? requestUri, System.Net.Http.HttpContent? content); Task<HttpResponseMessage> PatchAsync (string? requestUri, System.Net.Http.HttpContent? content);
Рассмотрим типовую отправку данных на самом простом примере - отправке текста.
Для отправки простого текстового содержимого применяется класс StringContent, который устанавливает отправляемую строку через конструктор:
StringContent content = new StringContent(отправляемая_строка);
Для тестирования вначале определим сервер - приложение ASP.NET Core.Для этого создадим проект по типу ASP.NET Core Empty:
К примеру, в моем случае проект называется HttpClientTestApp. Откроем в этом проекте в файл Program.cs
и определим в нем следующий код:
var builder = WebApplication.CreateBuilder(); var app = builder.Build(); app.MapPost("/data", async (HttpContext httpContext) => { using StreamReader reader = new StreamReader(httpContext.Request.Body); string name = await reader.ReadToEndAsync(); return $"Получены данные: {name}"; }); app.Run();
Для создания веб-приложения на ASP.NET Core вначале нам необходимо создать объект WebApplicationBuilder:
var builder = WebApplication.CreateBuilder();
Затем с помощью его метода Build создаем объект WebApplication, который собственно представляет приложение ASP.NET:
var app = builder.Build();
С помощью метода app.MapPost()
определяем конечную точку, которая будет обрабатывать POST-запросы по пути "/data". Обработчик этой конечной точки в качестве параметра принимает
контекст запроса - объект HttpContext:
app.MapPost("/data", async (HttpContext httpContext) =>
Поскольку в данном случае мы тестируем отправку строки, то данные запроса - httpContext.Request.Body
считываем в строку - в переменную name и затем возвращаем назад клиенту строку "Получены данные: {name}".
Затем запускаем приложение:
app.Run();
Теперь определим консольное приложение, в котором HttpClient будет отправлять веб-приложению какую-нибудь строку. Сначала используем метод SendAsync():
class Program { static HttpClient httpClient = new HttpClient(); static async Task Main() { StringContent content = new StringContent("Tom"); // определяем данные запроса using var request = new HttpRequestMessage(HttpMethod.Post, "https://localhost:7094/data"); // установка отправляемого содержимого request.Content = content; // отправляем запрос using var response = await httpClient.SendAsync(request); // получаем ответ string responseText = await response.Content.ReadAsStringAsync(); Console.WriteLine(responseText); } }
Для определения отправляемых данных создается объект StringContent. В его конструктор передается отправляемая строка.
Далее определяем объект HttpRequestMessage и устанавливаем его свойство Content
- содержимое, которое отправляется на сервер.
Далее с помощью метода SendAsync()
эти данные отправляются веб-приложению. В моем случае веб-приложение запущено по адресу "https://localhost:7094", соответственно POST-запрос отправляется по адресу "https://localhost:7094/data".
Ответ сервера считывается в строку и выводится на консоль. То есть после выполнения запроса мы должны увидеть на консоли:
Получены данные: Tom
Использование методов PostAsync/PactchAsync/PutAsync позволяет несколько упростить код. Так, изменим предыдущий пример, применив метод PostAsync():
class Program { static HttpClient httpClient = new HttpClient(); static async Task Main() { StringContent content = new StringContent("Tom"); using var response = await httpClient.PostAsync("https://localhost:7094/data", content); string responseText = await response.Content.ReadAsStringAsync(); Console.WriteLine(responseText); } }
Класс HttpContent имеет свойство Headers, которое представляет тип HttpContentHeaders и позволяет установить вместе с отправляемым содержимым заголовки запроса.
Это может быть актуально при отправке данных с помощью методов PostAsync()/PutAsync()/PatchAsync()
. Например:
class Program { static HttpClient httpClient = new HttpClient(); static async Task Main() { HttpContent content = new StringContent("Hello METANIT.COM"); // устанавливаем заголовок content.Headers.Add("SecreteCode", "Anything"); using var response = await httpClient.PostAsync("https://localhost:7094/", content); string responseText = await response.Content.ReadAsStringAsync(); Console.WriteLine(responseText); } }
В данном случае устанавливается кастомный заголовок "SecreteCode". Но стоит отметить, что с помощью HttpContentHeaders не все стандартные заголовки мы можем установить.