Développer des applications web distribuées a longtemps impliqué des configurations complexes et des abstractions lourdes. Pourtant, dans de nombreux scénarios, un protocole HTTP simple et direct suffit amplement. ASP.NET Web API offre une approche minimaliste pour exposer des endpoints RESTful sans la surcouche traditionnelle des frameworks plus imposants.
Voici comment mettre en place un service Web API et le consommer depuis un client .NET.
Mise en place du service API
Prérequis : Visual Studio et le gestionnaire de paquets NuGet.
- Créer un projet ASP.NET MVC vide.
- Ajouter le paquet Web API via NuGet (rechercher
AspNetWebApi). - Dans
Global.asax.cs, configurer le routage HTTP :
protected void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "service/{controller}/{action}/{param}",
defaults: new { param = RouteParameter.Optional }
);
}
- Créer un contrôleur
ProductControllerhéritant deApiController:
namespace DemoApi.Controllers
{
public class ProductController : ApiController
{
}
}
- Définir un modèle de données dans un dossier
Models:
namespace DemoApi.Models
{
public class Product
{
public int Identifier { get; set; }
public string Label { get; set; }
public string Description { get; set; }
}
}
- Ajouter une action au contrôleur pour récupérer une liste filtrée de produits :
public class ProductController : ApiController
{
public IEnumerable<Product> FetchProducts(int skip, int limit)
{
var catalog = new List<Product>
{
new Product { Identifier = 101, Label = "Ordinateur portable", Description = "PC portable haut de gamme" },
new Product { Identifier = 102, Label = "Clavier mécanique", Description = "Switches Cherry MX" },
new Product { Identifier = 103, Label = "Écran 4K", Description = "Résolution 3840x2160" },
new Product { Identifier = 104, Label = "Souris sans fil", Description = "Capteur optique 16000 DPI" },
new Product { Identifier = 105, Label = "Casque audio", Description = "Réduction de bruit active" }
};
return catalog
.Where(p => p.Identifier > skip)
.Take(limit)
.ToList();
}
}
- Lancer l'application et naviguer vers l'URL du endpoint. Le navigateur affiche directement le résultat, ce qui facilite grandement les tests.
Consommation du service depuis un client HttpClient
- Créer un projet de test de type bibliothèque de classes.
- Ajouter les paquets NuGet :
System.Net.Http,Newtonsoft.JsonetxUnit. - Écrire un test unitaire :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using Newtonsoft.Json;
using Xunit;
namespace ClientApiTests
{
public class ProductApiTests
{
[Fact]
public void Should_Retrieve_Filtered_Products()
{
// Préparer les paramètres au format JSON
var parameters = new { skip = 101, limit = 3 };
var serializedParams = JsonConvert.SerializeObject(parameters);
// Construire le contenu HTTP
var payload = new StringContent(serializedParams);
payload.Headers.ContentType = new MediaTypeHeaderValue("application/json");
// Envoyer la requête POST
using (var client = new HttpClient { BaseAddress = new Uri("http://localhost:5000/") })
{
var httpResponse = client.PostAsync("service/product/fetchproducts", payload).Result;
var jsonBody = httpResponse.Content.ReadAsStringAsync().Result;
// Désérialiser la réponse
var products = JsonConvert.DeserializeObject<List<Product>>(jsonBody);
// Afficher les résultats
foreach (var product in products)
{
Console.WriteLine($"{product.Label} : {product.Description}");
}
Assert.NotEmpty(products);
}
}
}
public class Product
{
public int Identifier { get; set; }
public string Label { get; set; }
public string Description { get; set; }
}
}
La requête envoie les paramètres sous forme JSON et spécifie application/json dans l'en-tête Content-Type. L'API retourne automatiquement une réponse JSON sans aucune modificatoin côté serveur. C'est le principe de négociation de contenu : un même endpoint peut servir du XML ou du JSON selon les préférences exprimées par le client.
Voici la réponse obtenue :
[
{"Identifier":102,"Label":"Clavier mécanique","Description":"Switches Cherry MX"},
{"Identifier":103,"Label":"Écran 4K","Description":"Résolution 3840x2160"},
{"Identifier":104,"Label":"Souris sans fil","Description":"Capteur optique 16000 DPI"}
]
Consommation depuis JavaScript
L'appel depuis le côté client en JavaScript suit une logique similaire :
var body = JSON.stringify({ skip: 101, limit: 3 });
fetch('/service/product/fetchproducts', {
method: 'POST',
headers: {
'Content-Type': 'application/json; charset=utf-8'
},
body: body
})
.then(response => response.json())
.then(data => {
data.forEach(function(item) {
document.getElementById('output')
.innerHTML += item.Label + ' : ' + item.Description + '<br/>';
});
});
Le même service répond à la fois aux appels .NET et JavaScript, sans duplication de code côté serveur.
Approche sans dépendance partagée
Pour garantir une véritable indépendance entre client et serveur — essentielle dans une architecture distribuée — il est possible de consommer la réponse JSON sans partager le modèle de données. Newtonsoft.Json permet de manipuler les données de manière dynamique :
var parsed = JArray.Parse(jsonBody);
foreach (var token in parsed)
{
Console.WriteLine($"{token["Label"]} : {token["Description"]}");
}
Cette approche élimine toute couplage fort entre les projets, le client interprétant simplement la structure JSON retournée par l'API.