Appeler une API web à partir d’un client .NET (C#)
Ce contenu est destiné à une version précédente de .NET. Le nouveau développement doit utiliser ASP.NET Core. Pour plus d’informations sur l’utilisation de l’API web ASP.NET Core, consultez :
- Tutoriel : Création d’une API web avec ASP.NET Core
- Appeler un point de terminaison HTTP à partir d’un client .NET
Téléchargez le projet terminé.
Ce tutoriel montre comment appeler une API web à partir d’une application .NET à l’aide de System.Net.Http.HttpClient.
Dans ce tutoriel, une application cliente qui utilise l’API web suivante est écrite :
Action | HTTP method | URI relatif |
---|---|---|
Obtenir un produit par ID | GET | /api/products/id |
Créer un produit | POST | /api/products |
Mettre à jour un produit | PUT | /api/products/id |
Supprimer un produit | Suppression | /api/products/id |
Pour savoir comment implémenter cette API avec API Web ASP.NET, consultez Création d’une API web qui prend en charge les opérations CRUD.
Par souci de simplicité, l’application cliente de ce didacticiel est une application console Windows. HttpClient est également pris en charge pour les applications Windows Phone et du Windows Store. Pour plus d’informations, consultez Écriture de code client d’API web pour plusieurs plateformes à l’aide de bibliothèques portables
NOTE: Si vous passez des URL de base et des URI relatifs en tant que valeurs codées en dur, gardez à l’esprit les règles d’utilisation de l’API HttpClient
. La HttpClient.BaseAddress
propriété doit être définie sur une adresse avec une barre oblique de fin (/
). Par exemple, lorsque vous passez des URI de ressource codés en dur à la HttpClient.GetAsync
méthode, n’incluez pas de barre oblique de début. Pour obtenir un Product
par ID :
- Définissez
client.BaseAddress = new Uri("https://localhost:5001/");
- Demandez un
Product
. Par exemple :client.GetAsync<Product>("api/products/4");
.
Création d'application console
Dans Visual Studio, créez une application console Windows nommée HttpClientSample et collez le code suivant :
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();
}
}
}
Le code précédent est l’application cliente complète.
RunAsync
s’exécute et se bloque jusqu’à ce qu’il se termine. La plupart des méthodes HttpClient sont asynchrones, car elles effectuent des E/S réseau. Toutes les tâches asynchrones sont effectuées à l’intérieur de RunAsync
. Normalement, une application ne bloque pas le thread main, mais cette application n’autorise aucune interaction.
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();
}
Installer les bibliothèques clientes d’API web
Utilisez le Gestionnaire de package NuGet pour installer le package bibliothèques clientes d’API web.
Dans le menu Outils, sélectionnez Gestionnaire de package NuGet>Console du Gestionnaire de package. Dans la console du Gestionnaire de package (PMC), tapez la commande suivante :
Install-Package Microsoft.AspNet.WebApi.Client
La commande précédente ajoute les packages NuGet suivants au projet :
- Microsoft.AspNet.WebApi.Client
- Newtonsoft.Json
Newtonsoft.Json (également appelé Json.NET) est un framework JSON hautes performances populaire pour .NET.
Ajouter une classe de modèle
Examiner la classe Product
:
public class Product
{
public string Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public string Category { get; set; }
}
Cette classe correspond au modèle de données utilisé par l’API web. Une application peut utiliser HttpClient pour lire un Product
instance à partir d’une réponse HTTP. L’application n’a pas besoin d’écrire de code de désérialisation.
Créer et initialiser HttpClient
Examinez la propriété HttpClient statique :
static HttpClient client = new HttpClient();
HttpClient est destiné à être instancié une seule fois et réutilisé tout au long de la vie d’une application. Les conditions suivantes peuvent entraîner des erreurs SocketException :
- Création d’un instance HttpClient par demande.
- Serveur sous une charge importante.
La création d’un instance HttpClient par requête peut épuiser les sockets disponibles.
Le code suivant initialise le instance 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"));
Le code précédent :
- Définit l’URI de base pour les requêtes HTTP. Remplacez le numéro de port par le port utilisé dans l’application serveur. L’application ne fonctionnera pas tant que le port de l’application serveur n’est pas utilisé.
- Définit l’en-tête Accepter sur « application/json ». La définition de cet en-tête indique au serveur d’envoyer des données au format JSON.
Envoyer une demande GET pour récupérer une ressource
Le code suivant envoie une demande GET pour un produit :
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;
}
La méthode GetAsync envoie la requête HTTP GET. Une fois la méthode terminée, elle retourne un HttpResponseMessage qui contient la réponse HTTP. Si le code status dans la réponse est un code de réussite, le corps de la réponse contient la représentation JSON d’un produit. Appelez ReadAsAsync pour désérialiser la charge utile JSON sur un Product
instance. La méthode ReadAsAsync est asynchrone, car le corps de la réponse peut être arbitrairement volumineux.
HttpClient ne lève pas d’exception lorsque la réponse HTTP contient un code d’erreur. Au lieu de cela, la propriété IsSuccessStatusCode a la valeur false si le status est un code d’erreur. Si vous préférez traiter les codes d’erreur HTTP comme des exceptions, appelez HttpResponseMessage.EnsureSuccessStatusCode sur l’objet de réponse. EnsureSuccessStatusCode
lève une exception si le code status se situe en dehors de la plage comprise entre 200 et 299. Notez que HttpClient peut lever des exceptions pour d’autres raisons, par exemple si la demande expire.
Media-Type formateurs à désérialiser
Lorsque ReadAsAsync est appelé sans paramètres, il utilise un ensemble par défaut de formateurs multimédias pour lire le corps de la réponse. Les formateurs par défaut prennent en charge les données encodées au format JSON, XML et Form-URL.
Au lieu d’utiliser les formateurs par défaut, vous pouvez fournir une liste de formateurs à la méthode ReadAsAsync . L’utilisation d’une liste de formateurs est utile si vous disposez d’un formateur de type média personnalisé :
var formatters = new List<MediaTypeFormatter>() {
new MyCustomFormatter(),
new JsonMediaTypeFormatter(),
new XmlMediaTypeFormatter()
};
resp.Content.ReadAsAsync<IEnumerable<Product>>(formatters);
Pour plus d’informations, consultez Formateurs multimédias dans API Web ASP.NET 2
Envoi d’une demande POST pour créer une ressource
Le code suivant envoie une requête POST qui contient une Product
instance au format 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;
}
La méthode PostAsJsonAsync :
- Sérialise un objet au format JSON.
- Envoie la charge utile JSON dans une requête POST.
Si la demande réussit :
- Il doit retourner une réponse 201 (Créé).
- La réponse doit inclure l’URL des ressources créées dans l’en-tête Location.
Envoi d’une demande PUT pour mettre à jour une ressource
Le code suivant envoie une demande PUT pour mettre à jour un produit :
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;
}
La méthode PutAsJsonAsync fonctionne comme PostAsJsonAsync, sauf qu’elle envoie une requête PUT au lieu de POST.
Envoi d’une demande DELETE pour supprimer une ressource
Le code suivant envoie une demande DELETE pour supprimer un produit :
static async Task<HttpStatusCode> DeleteProductAsync(string id)
{
HttpResponseMessage response = await client.DeleteAsync(
$"api/products/{id}");
return response.StatusCode;
}
Comme GET, une demande DELETE n’a pas de corps de requête. Vous n’avez pas besoin de spécifier le format JSON ou XML avec DELETE.
Tester l’exemple
Pour tester l’application cliente :
Téléchargez et exécutez l’application serveur. Vérifiez que l’application serveur fonctionne. Par exemple,
http://localhost:64195/api/products
doit retourner une liste de produits.Définissez l’URI de base pour les requêtes HTTP. Remplacez le numéro de port par le port utilisé dans l’application serveur.
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"));
Exécutez l’application cliente. La sortie suivante est produite :
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)