Activation des opérations CRUD dans API Web ASP.NET 1

par Mike Wasson

Télécharger le projet terminé

Ce tutoriel montre comment prendre en charge les opérations CRUD dans un service HTTP à l’aide de API Web ASP.NET pour ASP.NET 4.x.

Versions logicielles utilisées dans le tutoriel

  • Visual Studio 2012
  • API web 1 (fonctionne également avec l’API web 2)

CRUD signifie « Créer, lire, mettre à jour et supprimer », qui sont les quatre opérations de base de base de données. De nombreux services HTTP modélisent également des opérations CRUD via des API REST ou REST.

Dans ce tutoriel, vous allez créer une API web très simple pour gérer une liste de produits. Chaque produit contient un nom, un prix et une catégorie (par exemple, « jouets » ou « matériel »), ainsi qu’un ID de produit.

L’API products expose les méthodes suivantes.

Action HTTP method URI relatif
Obtenir la liste de tous les produits GET /api/products
Obtenir un produit par ID GET /api/products/id
Obtenir un produit par catégorie GET /api/products?category=category
Créer un produit POST /api/products
Mettre à jour un produit PUT /api/products/id
Supprimer un produit Suppression /api/products/id

Notez que certains URI incluent l’ID de produit dans le chemin d’accès. Par exemple, pour obtenir le produit dont l’ID est 28, le client envoie une requête GET pour http://hostname/api/products/28.

Ressources

L’API products définit des URI pour deux types de ressources :

Ressource URI
Liste de tous les produits. /api/products
Un produit individuel. /api/products/id

Méthodes

Les quatre méthodes HTTP main (GET, PUT, POST et DELETE) peuvent être mappées aux opérations CRUD comme suit :

  • GET récupère la représentation de la ressource à un URI spécifié. GET ne doit pas avoir d’effets secondaires sur le serveur.
  • PUT met à jour une ressource à un URI spécifié. PUT peut également être utilisé pour créer une ressource à un URI spécifié, si le serveur autorise les clients à spécifier de nouveaux URI. Pour ce tutoriel, l’API ne prend pas en charge la création via PUT.
  • POST crée une ressource. Le serveur affecte l’URI pour le nouvel objet et retourne cet URI dans le cadre du message de réponse.
  • DELETE supprime une ressource à un URI spécifié.

Remarque : La méthode PUT remplace l’entité de produit entière. Autrement dit, le client est censé envoyer une représentation complète du produit mis à jour. Si vous souhaitez prendre en charge les mises à jour partielles, la méthode PATCH est recommandée. Ce tutoriel n’implémente pas PATCH.

Créer un projet d’API web

Commencez par exécuter Visual Studio et sélectionnez Nouveau projet dans la page Démarrer . Ou, dans le menu Fichier , sélectionnez Nouveau , puis Projet.

Dans le volet Modèles , sélectionnez Modèles installés et développez le nœud Visual C# . Sous Visual C#, sélectionnez Web. Dans la liste des modèles de projet, sélectionnez ASP.NET application web MVC 4. Nommez le projet « ProductStore », puis cliquez sur OK.

Capture d’écran de la nouvelle fenêtre de projet, montrant les options de menu et mettant en surbrillance le chemin de création d’une application web A S P dot NET M V C 4.

Dans la boîte de dialogue Nouveau ASP.NET projet MVC 4 , sélectionnez API web , puis cliquez sur OK.

Capture d’écran du nouveau projet A S P dot NET, montrant des images encadrées de modèles disponibles et mettant en évidence le modèle Web A P I, en bleu.

Ajout d’un modèle

Un modèle est un objet qui représente les données dans votre application. Dans API Web ASP.NET, vous pouvez utiliser des objets CLR fortement typés comme modèles, et ils seront automatiquement sérialisés au format XML ou JSON pour le client.

Pour l’API ProductStore, nos données se composent de produits. Nous allons donc créer une classe nommée Product.

Si l’Explorateur de solutions n’est pas déjà visible, cliquez sur le menu Vue et sélectionnez Explorateur de solutions. Dans Explorateur de solutions, cliquez avec le bouton droit sur le dossier Modèles. Dans le menu contextuel, sélectionnez Ajouter, puis Classe. Nommez la classe « Product ».

Capture d’écran du menu de l’Explorateur de solutions, mettant en évidence la sélection pour les modèles afin d’afficher un menu supplémentaire pour sélectionner l’option Ajouter une classe.

Ajoutez les propriétés suivantes à la Product classe .

namespace ProductStore.Models
{
    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Category { get; set; }
        public decimal Price { get; set; }
    }
}

Ajout d'une base de données de référentiel

Nous devons stocker une collection de produits. Il est judicieux de séparer la collection de notre implémentation de service. De cette façon, nous pouvons modifier le magasin de stockage sans réécrire la classe de service. Ce type de conception est appelé modèle de dépôt . Commencez par définir une interface générique pour le dépôt.

Dans Explorateur de solutions, cliquez avec le bouton droit sur le dossier Modèles. Sélectionnez Ajouter, puis Nouveau élément.

Capture d’écran du menu de l’Explorateur de solutions, qui met en évidence l’option modèles et affiche un menu pour ajouter un nouvel élément.

Dans le volet Modèles , sélectionnez Modèles installés et développez le nœud C#. Sous C#, sélectionnez Code. Dans la liste des modèles de code, sélectionnez Interface. Nommez l’interface « IProductRepository ».

Capture d’écran du volet Modèles, montrant le menu modèles installé, qui met en évidence les options de code et d’interface en gris.

Ajoutez l’implémentation suivante :

namespace ProductStore.Models
{
    public interface IProductRepository
    {
        IEnumerable<Product> GetAll();
        Product Get(int id);
        Product Add(Product item);
        void Remove(int id);
        bool Update(Product item);
    }
}

Ajoutez maintenant une autre classe au dossier Models, nommée « ProductRepository ». Cette classe implémente l’interface IProductRepository . Ajoutez l’implémentation suivante :

namespace ProductStore.Models
{
    public class ProductRepository : IProductRepository
    {
        private List<Product> products = new List<Product>();
        private int _nextId = 1;

        public ProductRepository()
        {
            Add(new Product { Name = "Tomato soup", Category = "Groceries", Price = 1.39M });
            Add(new Product { Name = "Yo-yo", Category = "Toys", Price = 3.75M });
            Add(new Product { Name = "Hammer", Category = "Hardware", Price = 16.99M });
        }

        public IEnumerable<Product> GetAll()
        {
            return products;
        }

        public Product Get(int id)
        {
            return products.Find(p => p.Id == id);
        }

        public Product Add(Product item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }
            item.Id = _nextId++;
            products.Add(item);
            return item;
        }

        public void Remove(int id)
        {
            products.RemoveAll(p => p.Id == id);
        }

        public bool Update(Product item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }
            int index = products.FindIndex(p => p.Id == item.Id);
            if (index == -1)
            {
                return false;
            }
            products.RemoveAt(index);
            products.Add(item);
            return true;
        }
    }
}

Le dépôt conserve la liste en mémoire locale. C’est correct pour un tutoriel, mais dans une application réelle, vous devez stocker les données en externe, soit une base de données, soit dans un stockage cloud. Le modèle de dépôt facilite la modification de l’implémentation ultérieurement.

Ajout d’un contrôleur d’API web

Si vous avez travaillé avec ASP.NET MVC, vous connaissez déjà les contrôleurs. Dans API Web ASP.NET, un contrôleur est une classe qui gère les requêtes HTTP du client. L’Assistant Nouveau projet a créé deux contrôleurs pour vous lors de la création du projet. Pour les voir, développez le dossier Contrôleurs dans Explorateur de solutions.

  • HomeController est un contrôleur MVC ASP.NET traditionnel. Il est responsable de la distribution des pages HTML pour le site et n’est pas directement lié à notre API web.
  • ValuesController est un exemple de contrôleur WebAPI.

Continuez et supprimez ValeursController, en cliquant avec le bouton droit sur le fichier dans Explorateur de solutions et en sélectionnant Supprimer. Ajoutez maintenant un nouveau contrôleur, comme suit :

Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le dossier Contrôleurs. Sélectionnez Ajouter, puis Contrôleur.

Capture d’écran du menu de l’Explorateur de solutions, mettant en évidence la catégorie contrôleurs, qui apporte un autre menu, mettant en évidence le chemin d’accès pour ajouter un contrôleur.

Dans l’Assistant Ajouter un contrôleur , nommez le contrôleur « ProductsController ». Dans la liste déroulante Modèle , sélectionnez Contrôleur d’API vide. Cliquez ensuite sur Ajouter.

Capture d’écran de la fenêtre Ajouter un contrôleur, montrant le champ nom du contrôleur pour entrer un nom et une liste déroulante de modèles, sous options de génération de modèles.

Notes

Il n’est pas nécessaire de placer vos contrôleurs dans un dossier nommé Contrôleurs. Le nom du dossier n’est pas important ; il s’agit simplement d’un moyen pratique d’organiser vos fichiers sources.

L’Assistant Ajouter un contrôleur crée un fichier nommé ProductsController.cs dans le dossier Controllers. Si ce fichier n’est pas déjà ouvert, double-cliquez dessus pour l’ouvrir. Ajoutez l’instruction using suivante :

using ProductStore.Models;

Ajoutez un champ qui contient un instance IProductRepository.

public class ProductsController : ApiController
{
    static readonly IProductRepository repository = new ProductRepository();
}

Notes

L’appel new ProductRepository() du contrôleur n’est pas la meilleure conception, car il lie le contrôleur à une implémentation particulière de IProductRepository. Pour une meilleure approche, consultez Utilisation du programme de résolution des dépendances de l’API web.

Obtention d’une ressource

L’API ProductStore expose plusieurs actions « read » en tant que méthodes HTTP GET. Chaque action correspond à une méthode de la ProductsController classe .

Action HTTP method URI relatif
Obtenir la liste de tous les produits GET /api/products
Obtenir un produit par ID GET /api/products/id
Obtenir un produit par catégorie GET /api/products?category=category

Pour obtenir la liste de tous les produits, ajoutez cette méthode à la ProductsController classe :

public class ProductsController : ApiController
{
    public IEnumerable<Product> GetAllProducts()
    {
        return repository.GetAll();
    }
    // ....
}

Le nom de la méthode commence par « Get ». Par convention, il est mappé aux requêtes GET. En outre, comme la méthode n’a aucun paramètre, elle est mappée à un URI qui ne contient pas de segment « id » dans le chemin d’accès.

Pour obtenir un produit par ID, ajoutez cette méthode à la ProductsController classe :

public Product GetProduct(int id)
{
    Product item = repository.Get(id);
    if (item == null)
    {
        throw new HttpResponseException(HttpStatusCode.NotFound); 
    }
    return item;
}

Ce nom de méthode commence également par « Get », mais la méthode a un paramètre nommé id. Ce paramètre est mappé au segment « id » du chemin d’accès de l’URI. L’infrastructure API Web ASP.NET convertit automatiquement l’ID en type de données (int) correct pour le paramètre.

La méthode GetProduct lève une exception de type HttpResponseException si id n’est pas valide. Cette exception sera traduite par l’infrastructure en une erreur 404 (introuvable).

Enfin, ajoutez une méthode pour rechercher des produits par catégorie :

public IEnumerable<Product> GetProductsByCategory(string category)
{
    return repository.GetAll().Where(
        p => string.Equals(p.Category, category, StringComparison.OrdinalIgnoreCase));
}

Si l’URI de requête a une chaîne de requête, l’API web tente de faire correspondre les paramètres de requête aux paramètres de la méthode du contrôleur. Par conséquent, un URI de la forme « api/products?category=category » est mappé à cette méthode.

Création d’une ressource

Ensuite, nous allons ajouter une méthode à la ProductsController classe pour créer un produit. Voici une implémentation simple de la méthode :

// Not the final implementation!
public Product PostProduct(Product item)
{
    item = repository.Add(item);
    return item;
}

Notez deux choses à propos de cette méthode :

  • Le nom de la méthode commence par « Post... ». Pour créer un produit, le client envoie une requête HTTP POST.
  • La méthode prend un paramètre de type Product. Dans l’API Web, les paramètres avec des types complexes sont désérialisés à partir du corps de la requête. Par conséquent, nous nous attendons à ce que le client envoie une représentation sérialisée d’un objet produit, au format XML ou JSON.

Cette implémentation fonctionnera, mais elle n’est pas tout à fait terminée. Dans l’idéal, nous aimerions que la réponse HTTP inclue les éléments suivants :

  • Code de réponse : Par défaut, l’infrastructure d’API web définit la réponse status code sur 200 (OK). Toutefois, selon le protocole HTTP/1.1, lorsqu’une requête POST aboutit à la création d’une ressource, le serveur doit répondre avec status 201 (Créé).
  • Emplacement: Lorsque le serveur crée une ressource, il doit inclure l’URI de la nouvelle ressource dans l’en-tête Location de la réponse.

API Web ASP.NET facilite la manipulation du message de réponse HTTP. Voici l’implémentation améliorée :

public HttpResponseMessage PostProduct(Product item)
{
    item = repository.Add(item);
    var response = Request.CreateResponse<Product>(HttpStatusCode.Created, item);

    string uri = Url.Link("DefaultApi", new { id = item.Id });
    response.Headers.Location = new Uri(uri);
    return response;
}

Notez que le type de retour de méthode est maintenant HttpResponseMessage. En retournant un HttpResponseMessage au lieu d’un Produit, nous pouvons contrôler les détails du message de réponse HTTP, y compris le code status et l’en-tête Location.

La méthode CreateResponse crée un HttpResponseMessage et écrit automatiquement une représentation sérialisée de l’objet Product dans le corps du message de réponse.

Notes

Cet exemple ne valide pas .Product Pour plus d’informations sur la validation du modèle, consultez Validation du modèle dans API Web ASP.NET.

Mise à jour d’une ressource

La mise à jour d’un produit avec PUT est simple :

public void PutProduct(int id, Product product)
{
    product.Id = id;
    if (!repository.Update(product))
    {
        throw new HttpResponseException(HttpStatusCode.NotFound);
    }
}

Le nom de la méthode commence par « Put... », de sorte que l’API web le fait correspondre aux requêtes PUT. La méthode prend deux paramètres, l’ID de produit et le produit mis à jour. Le paramètre id est extrait du chemin d’accès de l’URI et le paramètre product est désérialisé à partir du corps de la requête. Par défaut, l’infrastructure API Web ASP.NET prend des types de paramètres simples à partir de l’itinéraire et des types complexes à partir du corps de la requête.

Suppression d’une ressource

Pour supprimer une ressource, définissez un « Supprimer... » Méthode.

public void DeleteProduct(int id)
{
    Product item = repository.Get(id);
    if (item == null)
    {
        throw new HttpResponseException(HttpStatusCode.NotFound);
    }

    repository.Remove(id);
}

Si une demande DELETE réussit, elle peut retourner status 200 (OK) avec un corps d’entité qui décrit le status ; status 202 (Accepté) si la suppression est toujours en attente; ou status 204 (Aucun contenu) sans corps d’entité. Dans ce cas, la DeleteProduct méthode ayant un void type de retour, API Web ASP.NET le traduit automatiquement en code status 204 (Aucun contenu).