Concevoir des APIs web avec ASP.NET MVC Web API

 

Le web continue de se remplir d’APIs web, ces services offerts par les sociétés de l’Internet qui permettent d’exploiter leurs données. Ils peuvent être sécurisés ou accessibles à quiconque ; gratuits ou payants ; en REST ou en SOAP ; et ont encore bien d’autres différences les uns avec les autres.

image

Source : ProgrammableWeb

Mais tous ont un but commun : offrir aux développeurs un moyen simple d’exploiter des données depuis une multitude de clients différents, du PC au téléphone en passant par la télévision connectée. Dans l’optique de simplifier la conception d’APIs Web, les équipes ASP.NET et WCF ont créé un tout nouveau framework : ASP.NET Web API.

Dans cet article nous verrons les bases du développement d’APIs Web avec ce dernier, nous survolerons les fonctionnalités plus avancées, et finirons avec quelques ressources complémentaires qui vous permettront de vous lancer dans le développement de votre première API Web avec ASP.NET Web API.

Comment ça marche ?

ASP.NET Web API est certes un nouveau framework de la stack ASP.NET, il n’en reprend pas moins les concepts fondamentaux introduits avec ASP.NET / ASP.NET MVC. En particulier, ses ressemblances avec ASP.NET MVC feront de l’apprentissage pour les développeurs l’ayant pratiqué, un vrai jeu d’enfant !

Rapide rappel d’ASP.NET MVC

Pour les autres, revenons rapidement sur ASP.NET MVC : ici, le but est de séparer la logique d’une application (en l’occurrence d’une application web) en trois parties distinctes :

· la vue : c’est la partie que voit l’utilisateur et avec laquelle il interagit, généralement faite d’HTML agrémenté de balises serveur, de CSS et de JavaScript pour l’interaction côté client.

· le contrôleur : c’est la partie serveur qui traite la demande, communique potentiellement avec une base de données et envoie une réponse au client.

· le modèle : c’est la donnée brute qui est traitée par le contrôleur et envoyée à la vue pour y être affichée.

Le contrôleur joue un rôle central car c’est lui qui reçoit la requête, traite les données du modèle et redirige vers la page qui convient. Chaque contrôleur est une classe .NET (généralement C# ou VB.NET) qui contient des méthodes que l’on appelle des actions car ce sont celles-ci que peut activer le client. Chaque action est définie par une URI définie par une ou plusieurs routes déclarée au lancement de l’application web. Le client va donc demander une action grâce à une URI ; l’action va être traitée et la vue associée à l’action, contenant les données de sortie, va être renvoyée au client.

Prenons un exemple : dans un site de recettes culinaires, on pourrait trouver un contrôleur Recette qui dispose d’une action AfficherTopRecettes permettant d’afficher les recettes les plus populaires et prenant un paramètre entier qui s’il est présent, filtre sur l’ID de la recette. Cette action peut être activée depuis l’adresse : https://www.contoso.com/recette/afficherTopRecettes/10

Ici, la « route » qui nous a permis d’arriver à l’action en question est : https://www.contoso.com/{contrôleur}/{action}/{paramètre}

Pour plus d’informations sur ASP.NET MVC voir les articles sur le site officiel : https://www.asp.net/mvc

Un fonctionnement similaire

ASP.NET Web API fonctionne sur le même principe : un client souhaite récupérer une donnée brute : pour cela il va passer par l’URI correspondant à l’action à effectuer. La requête va être passée au contrôleur en question, traitée par celui-ci, qui va potentiellement interroger une base de données pour en récupérer des données (modèle), qui seront finalement renvoyées au client.

Le fonctionnement est donc extrêmement similaire, cependant à deux exceptions prêtes :

· Bien évidemment, il n’y a pas de vues : les données sont sérialisée (XML ou JSON par défaut) et renvoyées directement au client.

· Contrairement à ASP.NET MVC, les actions sont par défaut implicites dans ASP.NET Web API : l’action à exécuter est déduite des paramètres passés dans la requête et du verbe HTTP (GET, POST, PUT, DELETE).

Par exemple, si nous décidons d’ajouter une partie Web API dans le site culinaire que je prenais comme exemple plus haut, nous pouvons imaginer faire des requêtes comme celles-ci :

· [GET] https://www.contoso.com/api/recette/ : renvoi toutes les recettes

· [GET] https://www.contoso.com/api/recette/1242 : renvoi la recette dont l’ID est 1242

· [DELETE] https://www.contoso.com/api/recette/1242 : supprime la recette dont l’ID est 1242

· [POST] https://www.contoso.com/api/recette/ : ajoute une nouvelle recette depuis les données de formulaire POST

· [PUT] https://www.contoso.com/api/recette/1242 : met à jour la recette dont l’ID est 1242 depuis les données de formulaire POST

Note : ASP.NET Web API, qui se base entièrement sur le protocole HTTP, s’inscrit donc dans le modèle REST de conception des services web.

Notre premier contrôleur ASP.NET Web API

Pour cela nous allons définir une classe qui étend ApiController et qui définit ces mêmes actions :

image

Quelques points à noter dans cette classe :

· Si le nom des actions commencent par le verbe HTTP (Get*, Post*, Put*, Delete*) auxquelles elles sont associées, les actions n’ont pas besoin d’être décorées. Dans le cas où l’on veut changer le nom, il suffit de rajouter l’attribut correspondant : ici, on a décoré la méthode ListAllReceipes d’un HttpGetAttribute pour signaler que la méthode devait être utilisée lors d’un GET.

· On utilise le pattern Repository pour toute la manipulation des données.

· On obtient l’instance courante du Repository via de l’injection de dépendance. Pour cela on a préalablement enregistré la classe qui va résoudre les dépendances : j’ai utilisé Unity, mais de nombreux autres projets permettent de le faire, tels que Ninject, Castle Windsor, etc.

· La méthode ListAllReceipes renvoi un IQueryable<T> : de cette manière il est possible de rajouter des paramètres à la requête pour ne prendre qu’un certain nombre de résultats ou faire de la pagination, sans récupérer tous les enregistrements de la base de données et ainsi gagner en performances.

· La méthode Post prend directement une instance de la classe Recette : la transformation des valeurs de formulaire en instance de classe est fait automatiquement, et peut être personnalisée.

· Il est possible d’autoriser seulement certains utilisateurs / rôles à accéder à certaines actions ; pour cela il suffit de rajouter un attribut de type AuthorizeAttribute sur les actions ou sur le contrôleur tout entier. Pour le reste, les autorisations se basent sur le modèle habituel d’authentification d’ASP.NET

Les fonctionnalités avancées

Il existe d’autres fonctionnalités qui viennent étoffer les possibilités d’ASP.NET Web API :

Négociation de contenus

Côté client, on peut préciser le type de formatage que l’on attend en sortie : via le header HTTP, Accept on peut demander explicitement que le retour soit formaté en XML ou en JSON. C’est la négociation de contenus (Content Negociation). Cela permet de renvoyer au client les données sous le format qui lui est le plus simple à traiter. On peut également personnaliser le formatage en ajoutant la prise en compte de nouveaux formats.

Validation

La validation des données est présente sous la même forme qu’ASP.NET MVC. On pourra décorer nos classes de modèle avec des attributs de System.ComponentModel.DataAnnotations tels que Required, Range, MaxLength, RegularExpression, etc. Ainsi les données seront automatiquement validées et les erreurs pourront être renvoyées côté client pour y être traitées.

Filtres

De même que dans ASP.NET MVC, il est possible de définir des classes qui vont intercepter les requêtes et exécuter du code : ce sont les filtres. Ces filtres pourront être ensuite utilisé globalement, ou bien être mis unitairement sur un contrôleur ou une action.

Requêtes avancées

Comme précisé précédemment, il est possible grâce au IQueryable<T> de rajouter des paramètres supplémentaires à la requête : sélection d’une plage de données, filtre, ordonnancement, etc.

Pour cela on va utiliser les conventions d’URI d’OData. Par exemple, la requête suivante nous permettra de récupérer les résultats de la 3ème page de 10 recettes, ordonnés par nom: https://www.contoso.com/api/recette/?$skip=20&$top=10&$orderby=Name

Personnalisation

Tout comme ASP.NET MVC, ASP.NET Web API peut être entièrement personnalisé : il est possible d’étendre toutes les classes du processus de traitement d’une requête pour l’adapter à ses besoins. On utilisera alors le même mécanisme de résolution des dépendances que celui utilisé avec le pattern Repository.

Pourquoi utiliser ASP.NET Web API

ASP.NET Web API est un framework très simple à mettre en place, qui n’en est pas moins puissant et personnalisable. Il s’intègre sans problème aux sites ASP.NET / ASP.NET MVC existant et peut être auto-hébergé depuis une application console par exemple.

Plus important encore, il embrasse le concept de programmation RESTful ce qui le rend utilisable depuis n’importe quel terminal capable de passer des requêtes HTTP. Comme le service peut en outre adapter le formatage des données renvoyées au client qui les demande, cela le rend particulièrement cohérent pour les scénarii de mobilité, ou d’interopérabilité multi-clients.

Quelques resources pour bien commencer

· Pour bien commencer, installez le framework depuis la page officielle : https://www.asp.net/web-api

· Un excellent tutorial qui entre particulièrement en détail dans le code côté client avec JQuery : https://stephenwalther.com/blog/archive/2012/03/05/introduction-to-the-asp-net-web-api.aspx

· Le blog d’Henrik Nielsen de l’équipe ASP.NET pour suivre toutes les nouveautés sur ASP.NET Web API : https://blogs.msdn.com/b/henrikn/

· Plus d’infos sur la négociation de contenus : https://www.tugberkugurlu.com/archive/asp-net-web-api-mediatypeformatters-with-mediatypemappings

 

- Sebastien Mornas -