Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Это содержимое предназначено для предыдущей версии .NET. Новая разработка должна использовать ASP.NET Core. Дополнительные сведения об использовании веб-API ASP.NET Core см. в следующей статье:
В этом руководстве показано, как вызвать веб-API из приложения .NET с помощью System.Net.Http.HttpClient.
В этой инструкции создается клиентское приложение, которое использует следующий web API.
| Действие | Метод HTTP | Относительный универсальный код ресурса (URI) |
|---|---|---|
| Получение сведений о продукте по идентификатору | GET | /api/products/id |
| Создание нового продукта | ПОСТ | /api/products |
| Обновление продукта | ЗАПИСАТЬ | /api/products/id |
| Удаление продукта | DELETE | /api/products/id |
Сведения о реализации этого API с помощью веб-API ASP.NET см. в статье "Создание веб-API, поддерживающего операции CRUD".
Для простоты клиентское приложение в этом руководстве является консольным приложением Windows. HttpClient также поддерживается для приложений Windows Phone и Магазина Windows. Дополнительные сведения см. в статье Написание клиентского кода веб-API для нескольких платформ с помощью переносимых библиотек
ПРИМЕЧАНИЕ: Если вы передаете базовые URL-адреса и относительные URI в виде жестко закодированных значений, помните о правилах использования HttpClient API. Свойство HttpClient.BaseAddress должно иметь адрес, оканчивающийся на косую черту (/). Например, при передаче жёстко закодированных URI ресурсов в метод HttpClient.GetAsync, не включайте начальную косую черту. Чтобы получить Product по идентификатору:
- Задайте значение
client.BaseAddress = new Uri("https://localhost:5001/");. - Запросите
Product. Например:client.GetAsync<Product>("api/products/4");.
Создание консольного приложения
В Visual Studio создайте новое консольное приложение Windows с именем HttpClientSample и вставьте в следующий код:
using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
namespace HttpClientSample
{
public class Product
{
public string Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public string Category { get; set; }
}
class Program
{
static HttpClient client = new HttpClient();
static void ShowProduct(Product product)
{
Console.WriteLine($"Name: {product.Name}\tPrice: " +
$"{product.Price}\tCategory: {product.Category}");
}
static async Task<Uri> CreateProductAsync(Product product)
{
HttpResponseMessage response = await client.PostAsJsonAsync(
"api/products", product);
response.EnsureSuccessStatusCode();
// return URI of the created resource.
return response.Headers.Location;
}
static async Task<Product> GetProductAsync(string path)
{
Product product = null;
HttpResponseMessage response = await client.GetAsync(path);
if (response.IsSuccessStatusCode)
{
product = await response.Content.ReadAsAsync<Product>();
}
return product;
}
static async Task<Product> UpdateProductAsync(Product product)
{
HttpResponseMessage response = await client.PutAsJsonAsync(
$"api/products/{product.Id}", product);
response.EnsureSuccessStatusCode();
// Deserialize the updated product from the response body.
product = await response.Content.ReadAsAsync<Product>();
return product;
}
static async Task<HttpStatusCode> DeleteProductAsync(string id)
{
HttpResponseMessage response = await client.DeleteAsync(
$"api/products/{id}");
return response.StatusCode;
}
static void Main()
{
RunAsync().GetAwaiter().GetResult();
}
static async Task RunAsync()
{
// Update port # in the following line.
client.BaseAddress = new Uri("http://localhost:64195/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
try
{
// Create a new product
Product product = new Product
{
Name = "Gizmo",
Price = 100,
Category = "Widgets"
};
var url = await CreateProductAsync(product);
Console.WriteLine($"Created at {url}");
// Get the product
product = await GetProductAsync(url.PathAndQuery);
ShowProduct(product);
// Update the product
Console.WriteLine("Updating price...");
product.Price = 80;
await UpdateProductAsync(product);
// Get the updated product
product = await GetProductAsync(url.PathAndQuery);
ShowProduct(product);
// Delete the product
var statusCode = await DeleteProductAsync(product.Id);
Console.WriteLine($"Deleted (HTTP Status = {(int)statusCode})");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
Console.ReadLine();
}
}
}
Приведенный выше код является полным клиентским приложением.
RunAsync выполняется и блокируется до завершения. Большинство методов HttpClient являются асинхронными, так как они выполняют сетевые операции ввода-вывода. Все асинхронные задачи выполняются внутри RunAsync. Как правило, приложение не блокирует основной поток, но это приложение не позволяет взаимодействовать.
static async Task RunAsync()
{
// Update port # in the following line.
client.BaseAddress = new Uri("http://localhost:64195/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
try
{
// Create a new product
Product product = new Product
{
Name = "Gizmo",
Price = 100,
Category = "Widgets"
};
var url = await CreateProductAsync(product);
Console.WriteLine($"Created at {url}");
// Get the product
product = await GetProductAsync(url.PathAndQuery);
ShowProduct(product);
// Update the product
Console.WriteLine("Updating price...");
product.Price = 80;
await UpdateProductAsync(product);
// Get the updated product
product = await GetProductAsync(url.PathAndQuery);
ShowProduct(product);
// Delete the product
var statusCode = await DeleteProductAsync(product.Id);
Console.WriteLine($"Deleted (HTTP Status = {(int)statusCode})");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
Console.ReadLine();
}
Установка клиентских библиотек веб-API
Используйте диспетчер пакетов NuGet для установки пакета клиентских библиотек веб-API.
В меню Tools выберите NuGet Package Manager>Package Manager Console. В консоли диспетчера пакетов (PMC) введите следующую команду:
Install-Package Microsoft.AspNet.WebApi.Client
Предыдущая команда добавляет в проект следующие пакеты NuGet:
- Microsoft.AspNet.WebApi.Client
- Newtonsoft.Json
Newtonsoft.Json (также известный как Json.NET) — это популярная высокопроизводительная платформа JSON для .NET.
Добавление класса модели
Product Проверьте класс:
public class Product
{
public string Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public string Category { get; set; }
}
Этот класс соответствует модели данных, используемой веб-API. Приложение может использовать HttpClient для чтения Product экземпляра из HTTP-ответа. Приложению не нужно писать код десериализации.
Создание и инициализация HttpClient
Проверьте статическое свойство HttpClient :
static HttpClient client = new HttpClient();
HttpClient предназначен для создания экземпляра один раз и повторного использования в течение всего времени существования приложения. Следующие условия могут привести к ошибкам SocketException :
- Создание нового экземпляра HttpClient для каждого запроса.
- Сервер под тяжелой нагрузкой.
Создание нового экземпляра HttpClient для каждого запроса может исчерпать доступные сокеты.
Следующий код инициализирует экземпляр HttpClient :
static async Task RunAsync()
{
// Update port # in the following line.
client.BaseAddress = new Uri("http://localhost:64195/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
Предыдущий код:
- Задает базовый универсальный код ресурса (URI) для HTTP-запросов. Измените номер порта на порт, используемый в серверном приложении. Приложение не будет работать, если порт для серверного приложения не используется.
- Устанавливает заголовок Accept со значением "application/json". Если задать этот заголовок, сервер отправляет данные в формате JSON.
Отправка запроса GET для получения ресурса
Следующий код отправляет запрос GET для продукта:
static async Task<Product> GetProductAsync(string path)
{
Product product = null;
HttpResponseMessage response = await client.GetAsync(path);
if (response.IsSuccessStatusCode)
{
product = await response.Content.ReadAsAsync<Product>();
}
return product;
}
Метод GetAsync отправляет HTTP-запрос GET. По завершении метода возвращается httpResponseMessage , содержащий http-ответ. Если код состояния в ответе является кодом успешного выполнения, текст ответа содержит представление JSON продукта.
Вызовите ReadAsAsync для десериализации данных JSON в Product экземпляр. Метод ReadAsAsync является асинхронным, так как тело отклика может быть произвольно большим.
HttpClient не создает исключение, если http-ответ содержит код ошибки. Вместо этого свойство IsSuccessStatusCodeимеет значение false , если состояние является кодом ошибки. Если вы предпочитаете рассматривать коды ошибок HTTP в качестве исключений, вызовите httpResponseMessage.EnsureSuccessStatusCode в объекте ответа.
EnsureSuccessStatusCode вызывает исключение, если код состояния выходит за пределы диапазона 200–299. Обратите внимание, что HttpClient может вызывать исключения по другим причинам, например, если время ожидания запроса истекает.
Форматеры типа media для десериализации
При вызове ReadAsAsync без параметров используется набор форматировщиков мультимедиа по умолчанию для чтения текста ответа. Форматировщики по умолчанию поддерживают данные в кодировке JSON, XML и Form-url.
Вместо использования средств форматирования по умолчанию можно указать список средств форматирования методу ReadAsAsync . Использование списка средств форматирования полезно, если у вас есть настраиваемый модуль форматирования типа мультимедиа:
var formatters = new List<MediaTypeFormatter>() {
new MyCustomFormatter(),
new JsonMediaTypeFormatter(),
new XmlMediaTypeFormatter()
};
resp.Content.ReadAsAsync<IEnumerable<Product>>(formatters);
Дополнительные сведения см. в разделе "Формататоры мультимедиа" в веб-API ASP.NET 2
Отправка запроса POST для создания ресурса
Следующий код отправляет запрос POST, содержащий Product экземпляр в формате JSON:
static async Task<Uri> CreateProductAsync(Product product)
{
HttpResponseMessage response = await client.PostAsJsonAsync(
"api/products", product);
response.EnsureSuccessStatusCode();
// return URI of the created resource.
return response.Headers.Location;
}
Метод PostAsJsonAsync :
- Сериализует объект в JSON.
- Отправляет полезные данные JSON в запросе POST.
Если запрос выполнен успешно:
- Он должен возвращать ответ 201 (Создано).
- Ответ должен содержать URL-адрес созданных ресурсов в заголовке location.
Отправка запроса PUT для обновления ресурса
Следующий код отправляет запрос PUT для обновления продукта:
static async Task<Product> UpdateProductAsync(Product product)
{
HttpResponseMessage response = await client.PutAsJsonAsync(
$"api/products/{product.Id}", product);
response.EnsureSuccessStatusCode();
// Deserialize the updated product from the response body.
product = await response.Content.ReadAsAsync<Product>();
return product;
}
Метод PutAsJsonAsync работает как PostAsJsonAsync, за исключением того, что он отправляет запрос PUT вместо POST.
Отправка запроса DELETE для удаления ресурса
Следующий код отправляет запрос DELETE для удаления продукта:
static async Task<HttpStatusCode> DeleteProductAsync(string id)
{
HttpResponseMessage response = await client.DeleteAsync(
$"api/products/{id}");
return response.StatusCode;
}
Как и GET, запрос DELETE не имеет текста запроса. Вам не нужно указывать формат JSON или XML с помощью DELETE.
Тестирование примера
Чтобы протестировать клиентское приложение, выполните следующие действия.
Скачайте и запустите серверные приложения. Проверка работы серверного приложения. Например,
http://localhost:64195/api/productsдолжен возвращать список продуктов.Задайте базовый универсальный код ресурса (URI) для HTTP-запросов. Измените номер порта на порт, используемый в серверном приложении.
static async Task RunAsync() { // Update port # in the following line. client.BaseAddress = new Uri("http://localhost:64195/"); client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/json"));Запустите клиентское приложение. Выводятся следующие результаты:
Created at http://localhost:64195/api/products/4 Name: Gizmo Price: 100.0 Category: Widgets Updating price... Name: Gizmo Price: 80.0 Category: Widgets Deleted (HTTP Status = 204)