Home - About me - Browse by categories

[ASPNET Web API] Forcer le content type pour une action donnée

Avec ASP.NET Web API, la content négociation se fait à l’aide du header Accept de la requête HTTP. Lorsque le type demandé n’est pas pris en charge, la requête est alors traitée avec le formateur par défaut, en l’occurrence le formateur JSON.

Cependant, dans certains cas il est nécessaire de forcer  le format de retour de la requête. Par exemple pour retourner un flux RSS.

Considérons le code suivant :

public class RssController : ApiController
{
private readonly IBlogService _blogService;
public RssController()
{
var dbContext = new MetroBlogDbContext();
_blogService = new BlogService(dbContext);
}

public IEnumerable<Post> Get()
{
return _blogService.GetLatestPosts(true, 0, 20).ToList();
}
}

Il s’agit d’un simple contrôleur Web API qui retourne une liste d’objet Post (la définition n’a pas d’importance ici). Pour être capable de retourner un format de flux RSS, j’ai écrit un custom formatter pour RSS/Atom (cf. http://www.strathweb.com/2012/04/rss-atom-mediatypeformatter-for-asp-net-webapi/).

Une fois le formateur développé, il suffit de l’enregistrer au démarrage de l’application :

GlobalConfiguration.Configuration.Formatters.Add(new SyndicationFeedFormatter());

Cette solution permet de faire en sorte que lorsque le header Accept de la requête HTTP est à <em>application/rss+xml</em> ou <em>application/atom+xml</em>, le formateur SyndicationFeedFormatter soit utilisé et donc que le format en sortie soit un flux RSS. Ce n’est cependant pas suffisant pour que l’action Get renvoie toujours un flux RSS!

Pour le forcer, il est nécessaire de modifier le code de l’action Get et de créer nous même l’HttpResponseMessage qui sera renvoyé :

public HttpResponseMessage Get()
{
try
{
var posts = _blogService.GetLatestPosts(true, 0, 20).ToList();
var responseMessage = new HttpResponseMessage(HttpStatusCode.OK);
responseMessage.Content = new ObjectContent(typeof(IEnumerable<Post>), posts, new SyndicationFeedFormatter());
responseMessage.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/rss+xml");
return responseMessage;
}
catch(Exception ex)
{
throw new HttpResponseException(HttpStatusCode.InternalServerError);
}
}

A partir de là, quelque soit le header Accept qui est envoyé, le format retourné sera <em>application/rss+xml</em>.

Il est également possible de filtrer certains type en se basant sur le header Accept de la requête afin de forcer le format que dans certains cas :

public HttpResponseMessage Get()
{
try
{
var posts = _blogService.GetLatestPosts(true, 0, 20).ToList();
var responseMessage = new HttpResponseMessage(HttpStatusCode.OK);

if (Request.Headers.Accept.Any(a => a.MediaType == "application/json"))
{
responseMessage.Content = new ObjectContent(typeof(IEnumerable<Post>), posts, new JsonMediaTypeFormatter());
responseMessage.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
}
else
{
responseMessage.Content = new ObjectContent(typeof(IEnumerable<Post>), posts, new SyndicationFeedFormatter());
responseMessage.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/rss+xml");
}

return responseMessage;
}
catch(Exception ex)
{
throw new HttpResponseException(HttpStatusCode.InternalServerError);
}
}

Dans le cas présent, si le header Accept de la requête contient le media type <em>application/json</em>, on renvoie un retour en JSON, sinon on renvoie le flux RSS formaté.

A bientôt !

read more

[ASP.NET MVC 4] Mise en place de l’authentification OAuth Facebook

L’une des nouveautés d’ASP.NET MVC 4 est la possibilité de mettre en place très simplement de l’authentification au travers de fournisseurs d’identité tels que Facebook, Microsoft, Google (etc.) dans une application. Ce type d’authentification est d’ailleurs proposée de base dans les nouveaux modèles de projets d’application ASP.NET MVC 4 de Visual Studio. Cependant, afin de bien comprendre comment mettre en place les différentes briques qui permettront cette authentification, je vous propose de partir de zéro et de créer un projet à l’aide du modèle Basic :

image

##

Déroulement de l’authentification

Le processus d’authentification à l’aide d’un fournisseur d’identité externe se déroule en plusieurs étapes décrites sur le schéma ci-dessous :

image

Dans un premier temps, l’utilisateur choisi le fournisseur d’identité (parmi ceux proposés par l’application) avec lequel il souhaite s’authentifier. Il est alors redirigé vers la page d’authentification du fournisseur choisi. L’utilisateur s’authentifie et est renvoyé sur l’application à l’aide d’une URL de callback qui a été transmise au fournisseur d’identité lors de la venue de l’utilisateur. Dans la dernière étape, l’application valide l’utilisateur et récupère son identité (établie par le fournisseur).

Il est alors possible de récupérer 4 informations :

  • L’état de l’authentification (échec ou succès)
  • Le nom d’utilisateur (si succès, transmis par le fournisseur)
  • L’id de l’utilisateur (si succès, transmis par le fournisseur)
  • Le nom du fournisseur

Ajout des références nécessaires à la mise en place de l’authentification OAuth

La mise en place de l’authentification OAuth requière l’ajout de plusieurs références au projet. Il est possible d’en récupérer la plupart à l’aide du package nuget  DotNetOpenOAuth extensions for ASP.NET (WebPages). Une fois le package installé, il ne reste qu’à ajouter une référence vers la librairie Microsoft.Web.WebPages.OAuth.dll depuis la fenêtre d’ajout de référence de Visual Studio.

Voilà les références que vous devriez avoir à ce stade :

image

Configuration des fournisseurs d’identités

Afin que l’authentification puisse fonctionner, il est nécessaire de configurer les différents fournisseurs d’identités à utiliser dans l’application. Dans le cas présent, nous allons voir comment configurer Facebook.

Pour commencer, créez une nouvelle classe dans le dossier App_Start du projet. Nommez la OAuthConfig. Cette classe possède une méthode statique RegisterOAuthProviders qui sera en charge d’initialiser les différents fournisseurs d’identités au démarrage de l’application :

public class OAuthConfig
{
public static void RegisterOAuthProviders()
{
//enregistrement des fournisseurs d'identité
}
}

Appelez cette méthode dans le Global.asax :

public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();

WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);

//enregistrement des fournisseurs d'identités
OAuthConfig.RegisterOAuthProviders();
}
}

L’enregistrement des différents fournisseurs va se faire à l’aide de la classe OAuthWebSecurity définie dans l’espace de noms Microsoft.Web.WebPages.OAuth. Celle-ci possède un certain nombre de méthodes statiques pour enregistrer les différents fournisseurs supportés nativement (RegisterFacebookClient, RegisterMicrosoftClient…).

Configuration de l’authentification Facebook

Avant de procéder à l’enregistrement du fournisseur, il est nécessaire de se connecter sur https://developers.facebook.com/apps et de créer une nouvelle application. Pour se faire, cliquez sur le bouton <em>+ Create New App</em> en haut à droite. Donnez un nom à l’application et validez en cliquant sur <em>Continue</em>.

image

Entrez le code de sécurité pour terminer la création. Pour que l’authentification fonctionne, il est nécessaire de cocher Website with Facebook Login en bas de page et de renseigner l’URL du site web qui va utiliser l’application Facebook pour l’authentification. En l’occurrence ici votre URL de débogue dans Visual Studio :

image

Validez en cliquant sur Save Changes.

Il vous faut alors récupérer l’App ID et l’App Secret en haut de la page, afin d’enregistrer le fournisseur dans Visual Studio.

image

Pour enregistrer le fournisseur, il suffit d’appeler la méthode RegisterFacebookClient de la classe OAuthWebSecurity :

OAuthWebSecurity.RegisterFacebookClient(
appId:"[appId]",
appSecret:"[appSecret]",
displayName: "Facebook"
);

Création de la page de Login

Ajoutez un contrôleur <em>Account</em> et créez une action Login. Le modèle passé à la vue correspond à la liste des fournisseurs configurés (ici Facebook), représentée par la propriété RegisteredProviders sur la classe OAuthWebSecurity :

public class AccountController : Controller
{
public ActionResult Login()
{
return View(OAuthWebSecurity.RegisteredClientData);
}
}

La page affiche alors un bouton pour chaque fournisseur :

@model ICollection<AuthenticationClientData>

@{
ViewBag.Title = "Authentification";
}

## Choisissez un fournisseur d'identité pour vous identifier

@using (Html.BeginForm("Login", "Account", FormMethod.Post))
{
foreach (var provider in Model)
{
<input type="submit" name="provider" value="@provider.DisplayName" />

}
}

Le code appelé lors du POST du formulaire effectue la redirection vers le fournisseur sélectionné, en lui passant la callback URL (appelée après l’authentification par le fournisseur d’identité) :

[HttpPost]
public ActionResult Login(string provider)
{
string callbackUrl = Url.Action("ProviderCallback", "Account");
OAuthWebSecurity.RequestAuthentication(provider);
return new EmptyResult();
}

Lancez l’application, rendez-vous sur la page /Account/Login et vérifiez qu’un bouton Facebook apparait bien :

image

En cliquant sur le bouton, vous devriez être redirigé sur Facebook. Authentifiez-vous, acceptez d’utiliser l’application. Vous devriez alors être renvoyé sur votre site (sur l’action ProviderCallback). Pour le moment, vous devez obtenir une erreur 404.

image

Dans l’action de callback, il s’agit de vérifier que l’authentification a bien fonctionné. Pour cela, il faut utiliser la méthode VerifyAuthentication sur la classe OAuthWebSecurity. Si le résultat est valide, vous pouvez alors récupérer le nom et l’id de l’utilisateur et créer une session (à l’aide de la classe FormsAuthentication, par exemple) :

public ActionResult ProviderCallback()
{
var result = OAuthWebSecurity.VerifyAuthentication();
if (result.IsSuccessful)
{
string userName = result.UserName;
string userId = result.ProviderUserId;
FormsAuthentication.SetAuthCookie(userName, false);
return RedirectToAction("Index", "Home");
}
else
{
return RedirectToAction("Login", "Account");
}
}

Et voilà, le tour est joué, votre utilisateur est authentifié via Facebook.

Le mécanisme d’authentification est ultra générique ici, puisqu’il suffit de rajouter des fournisseurs (Microsoft, Google, Twitter, Yahoo…) dans la méthode RegisterOAuthProviders de la classe OAuthConfig créée au début de cet article !

Le code source de l’application d’exemple est disponible ici : https://juliencorioland.blob.core.windows.net/publicfiles/MVC4.ArticleOAuth.zip

A bientôt image

read more

Authentification Hybride Forms et ACS dans une application ASP.NET MVC hébergée dans Azure

Pour un projet, j’ai du mettre en place un mode d’authentification hybride Forms / ACS (Access Control Service) au sein d’une même application ASP.NET MVC, hébergée dans Azure.

Pour la partie Forms Authentication, je me suis basé sur un custom membership provider qui travaille avec le stockage par table de Windows Azure. Vous pouvez également utiliser les Azure Storage providers disponibles sur CodePlex ou NuGet. Je ne détaillerai pas la configuration de ce type d’authentification qui a déjà été traité dans pas mal d’articles sur le net.

Je souhaitais absolument avoir un mécanisme d’authentification qui soit peu intrusif, et surtout éviter d’avoir à gérer deux types d’authentification techniquement distincts dans mon code (si je suis en ACS alors la déconnexion se fait comme cela, si je suis en Forms alors …). Du coup, j’ai décidé d’utiliser ACS uniquement comme mécanisme d’authentification et du coup comme autorité d’identification des mes utilisateurs.

Pour se faire, j’ai tout d’abord configuré mon espace de noms ACS sur le portail d’administration Windows Azure. Pour voir comment faire cela pas à pas, je vous invite à lire ce billet sur le blog de Léo.

Une fois ACS configuré, il est possible de gérer l’authentification via ACS (et donc Windows Identity Foundation) de plusieurs manières : la première, en utilisant le fichier Web.config et en configurant les bons HTTP module fournis avec le SDK WIF. Lors de la callback d’ACS (après authentification Windows Live, Facebook ou Yahoo…) les modules se chargeront automatiquement de récupérer l’identité de l’utilisateur ainsi que de retourner ses claims (propriétés qui identifient l’utilisateur, telles que son identifiant, son email, son nom… en fonction de ce qui a été configuré sur ACS).

L’autre solution consiste à ne pas utiliser la configuration automatique de WIF et de catcher manuellement la réponse d’ACS après que l’utilisateur soit authentifié. Pour cela, il suffit d’écrire un peu de code, mais rien de bien méchant !

Avant tout, il est nécessaire d’ajouter deux références au projet : Microsoft.IdentityModel.dll (disponible dans le GAC après avoir installé le SDK WIF) et System.IdentityModel.dll.

Il faut commencer par vérifier que la requête HTTP est bien issue d’une callback d’ACS. Pour se faire, on utilise le module WSFederationAuthenticationModule qui fournit des outils pour interpréter les réponses d’ACS en mode WS-Federation :

WSFederationAuthenticationModule wsFedAuthModule = new WSFederationAuthenticationModule();
if (!wsFedAuthModule.IsSignInResponse(request))
throw new HttpException(403, "forbidden");

Ensuite, il est possible de récupérer la réponse sous la forme d’un objet de type SignInResponseMessage :

var signInResponseMessage = wsFedAuthModule.GetSignInResponseMessage(System.Web.HttpContext.Current.Request);

La récupération des claims renvoyé par le STS (Secure Token Service) d’ACS se fait ensuite à l’aide du WSFederationSerializer, qui permet notamment de récupérer le secure token de la réponse :

var serializationContext =
new WSTrustSerializationContext(SecurityTokenHandlerCollectionManager.CreateDefaultSecurityTokenHandlerCollectionManager());
var secureTokenResponse = new WSFederationSerializer().CreateResponse(signInResponseMessage, serializationContext);

La réponse qui est récupérée contient le token de sécurité renvoyé par ACS. Celui-ci contient les différentes informations relative à l’utilisateur et est chiffré. Il est nécessaire d’utiliser un Saml2SecurityTokenHandler afin d’accéder aux informations du token. Avant, il est nécessaire de récupérer l’emprunte du certificat utilisé par ACS, l’espace de nom ACS, ainsi que la liste des URIs autorisées à travailler avec ACS (en fonction de votre configuration, je vous renvoie vers l’article de Léo évoqué plus tôt) :

ConfigurationBasedIssuerNameRegistry issuers = new ConfigurationBasedIssuerNameRegistry();
string certificateTumbprint = "<certificat tumbprint>";
var ascNamespace = "https://votrenamespace.accesscontrol.windows.net/";
issuers.AddTrustedIssuer(certificateTumbprint, ascNamespace);

Saml2SecurityTokenHandler tokenHandler = new Saml2SecurityTokenHandler
{
CertificateValidator = X509CertificateValidator.None
};

SecurityTokenHandlerConfiguration config = new SecurityTokenHandlerConfiguration
{
CertificateValidator = X509CertificateValidator.None,
IssuerNameRegistry = issuers
};

config.AudienceRestriction.AllowedAudienceUris.Add(new Uri("http://127.0.0.1"));
tokenHandler.Configuration = config;

Maintenant que le token handler est correctement configuré il ne reste qu’à utiliser un simple XmlReader pour lire le security token et en extraire la collection de **ClaimsIdentity** qu’il transporte :

using (var reader = XmlReader.Create(new StringReader(secureTokenResponse.RequestedSecurityToken.SecurityTokenXml.OuterXml)))
{
SecurityToken token = tokenHandler.ReadToken(reader);
ClaimsIdentityCollection claimsIdentity = tokenHandler.ValidateToken(token);
}

Chaque ClaimsIdentity contenu dans la collection possède alors une collection Claims, retournant chacun des claim associé à l’utilisateur qui s’est connecté. Il ne reste qu’à implémenter votre propre logique pour créer le cookie de session de l’utilisateur (à l’aide de la méthode SetAuthCookie de la classe FormsAuthentication, par exemple).

Il est donc possible d’avoir un contrôle vraiment fin sur l’authentification d’un utilisateur via ACS, permettant ici d’inter-opérer simplement avec un autre mécanisme d’authentification !

A bientôt image

read more

[ASP.NET MVC] Premiers pas avec les ASP.NET Web API - Partie 2

Dans mon article précédent, je vous expliquais comment mettre en place les nouveaux contrôleurs Web API pour exposer vos données de manière RESTful. Je m’étais arrêté à la partie ASP.NET MVC Web API pure. Dans cet article, je souhaite fournir un exemple d’interface graphique venant consommer ces APIs.

J’ai choisi de développer l’interface en HTML/jQuery pur au sein du même projet que celui hébergeant mon API contrôleur. Ce qu’il faut bien comprendre ici, c’est que j’aurai pu faire le choix de n’importe quelle technologie capable d’envoyer une requête HTTP et de traiter du JSON (du texte, au final) : Windows Phone, Windows 8, iPhone, PHP… Bref, n’importe quelle plateforme de développement suffisamment récente (ou presque!).

###

Définition de l’interface graphique

L’interface graphique que j’ai choisi est ultra simple :

<div style="margin: 20px">
## Consommation des WEB Api

### Liste des requêtes

<a id="showRequestsLink" title="afficher les requêtes" href="#">afficher les requêtes</a>

<div id="requestsList">

### Ajouter une requête

<div id="addFormContainer">
<form id="addRequestForm">
Titre : <input type="text" name="Title" id="Title" />
Description : <input type="text" name="Description" id="Description" />
<input type="hidden" name="Id" id="Id" value="" />
<input type="button" id="addRequestButton" value="Ajouter" />
</form>

Voilà ce que cela donne dans un navigateur :

image

Ensuite, tout se passe en ajax (et en HTTP!!).

Affichage de la liste des requêtes

Lorsque l’utilisateur clique sur le lien pour afficher la liste des requêtes, il est nécessaire de faire un GET sur l’URL /api/featurerequest, ce qui aura pour effet d’appeler l’action Get de l’ApiController développé dans l’article précédent.

function updateRequests() {
$.get("/api/featurerequests", function (requests) {
if (requests.length == 0) {
$("#requestsList").html("aucune requête dans la base de données

");
}
else {
$("#requestsList").html("");
$("#requestTemplate").tmpl(requests).appendTo("#requestsList");

handleLinksClicks();
}
});
}

$(document).ready(function () {

$("#showRequestsLink").click(function (evt) {
updateRequests();
});
});

L’appel en GET de l’url /api/featurerequests retourne directement un tableau d’objet JavaScript qui possède les mêmes propriétés que l’objet server FeatureRequest, celui-ci ayant automatiquement été sérialisé en JSON par le moteur Web API. Notez au passage que j’utilise ici le plugin jQuery tmpl, permettant d’effectuer un rendu à partir d’un template HTML. Vous pouvez récupérer directement ce plugin via la console Nuget de Visual Studio :

image

Voilà la structure du template que j’ai défini :

<script id="requestTemplate" type="text/html">
 - [Détail](#) | [Détail](#) | [Détail](#)

</script>

Note : chacune des propriétés de l’objet JSON peut être appelé à l’aide de la notation au sein du template ! (au passage, il s’agit d’un plugin jQuery développé par Microsoft image, on sent l’influence du binding XAML)

###

Ajouter/Mettre à jour une requête dans la base de données

Pour ajouter une nouvelle requête dans la base de données, il suffit de poster le formulaire sur l’URL /api/featurerequests. La requête sera alors automatiquement traitée par l’action qui lui correspond dans le contrôleur développé. Pour mettre à jour une requête, il suffit d’envoyer une requête HTTP PUT sur la même URL, avec les données du formulaire, sérialisées :

$("#addRequestButton").click(function (evt) {
evt.preventDefault();
var addRequestForm = $("#addRequestForm");
if ($("#Id").val() != "") {
$.ajax({
url: "/api/featurerequests/" + $("#Id").val(),
type: "PUT",
data: addRequestForm.serialize(),
success: function () {
updateRequests();
$("#Id").val("");
$("#Title").val("");
$("#Description").val("");
$("#addRequestButton").val("Ajouter");
},
error: function () {
alert("Erreur lors de la mise à jour");
}
});
}
else {
$.post("/api/featurerequests", addRequestForm.serialize())
.success(function (result) {
$("#Title").val("");
$("#Description").val("");
updateRequests();
})
.error(function () {
alert("Une erreur s'est produite!");
});
}
});

###

Récupérer les informations propres à une requête

Pour récupérer une information propre à une requête, il suffit d’envoyer une requête HTTP GET à l’url /api/featurerequests/id :

$(".request-detail-link").click(function () {
var dataId = $(this).data("id");
var url = "/api/featurerequests/" + dataId;
$.get(url, function (jsonResult) {
alert(JSON.stringify(jsonResult));
});
});

Suppression d’une requête

Cette fonctionnalité est similaire à la récupération d’informations propres à une requête, à la différence près qu’il faut envoyer une requête HTTP DELETE :

$(".request-delete-link").click(function () {
var dataId = $(this).data("id");
if (confirm("Êtes-vous sûr de supprimer cette requête ?")) {
$.ajax({
url: "/api/featurerequests/" + dataId,
type: "DELETE",
success: function () {
alert("La requête a été supprimée");
updateRequests();
}
});
}
});

Conclusion / Résumé

L’important ici n’était pas tant le code JavaScript / HTML, mais plutôt de voir comment consommer très simplement les données à l’aide de requête HTTP et donc potentiellement depuis n’importe quelle plateforme récente image

Ci-dessous un résumé des différentes requêtes / verbes et de leurs actions respectives dans le contrôleur :

  • GET /api/featurerequests : GetFeatureRequests –> retourne la liste des requêtes

  • GET /api/featurerequests/id : GetFeatureRequest –> retourne une requête en particulier

  • POST /api/featurerequests : PostFeatureRequest –> ajouter une requête dans la base

  • PUT /api/featurerequests : PutFeatureRequest –> mise à jour d’une requête dans la base

  • DELETE /api/featurerequests/id : DeleteFeatureRequest –> suppression d’une requête de la base

Vous pouvez récupérer le code source ici.

A bientôt ! image

read more

[ASP.NET MVC] Premiers pas avec les ASP.NET Web API - Partie 1

Introduction

ASP.NET MVC 4 a été rendu disponible par Microsoft il y a peu et apporte son lot de nouveautés. Parmi celles-ci, on constate l’apparition d’une nouvelle brique : ASP.NET Web API. Il s’agit d’un Framework qui permet de développer rapidement et simplement des services HTTP pour la mise à disposition de données cross-plateforme et le développement d’application RESTful !

Dans ce post, je vous propose de créer une application reposant sur ce Framework et permettant de poster des requêtes de fonctionnalités / feedback pour un produit, comme le fait par exemple Uservoice.com (en beaucoup plus simple, évidemment).

Avant de commencer, il vous faut installer ASP.NET MVC 4. Pour cela, rendez-vous sur cette page et cliquez sur Install ASP.NET MVC 4.

Note : il est possible de développer des applications ASP.NET MVC 4 / ASP.NET Web API aussi bien dans Visual Studio 2010 que 2012, avec le .NET Framework 4.0 ou 4.5. Pour ma part, j’utiliserai Visual Studio 2012 et le .NET Framework 4.5.

Création du projet

Dans Visual Studio, créez un nouveau projet Web, de type ASP.NET MVC 4 Web Application :

image

Dans la fenêtre qui suit, choisissez un modèle de projet de type Web API. Gardez Razor comme moteur de vue, et validez la création du projet :

image

Analyse de la solution

Avant d’ajouter la moindre ligne de code au projet, nous allons nous intéresser à ce qui a été généré par Visual Studio. S’il s’agit de votre premier projet ASP.NET MVC 4, vous devez remarquer qu’un nouveau dossier App_Start est présent dès la création du projet. Celui-ci contient un ensemble de classes utilisées pour l’initialisation de l’application, dans la méthode Application_Start du fichier Global.asax!

Visual Studio a également créé deux contrôleurs :

HomeController : il s’agit d’un contrôleur ASP.NET MVC classique, composé d’une action Index pour renvoyer l’utilisateur sur la page d’accueil lorsqu’il se connecte sur le site. C’est ce contrôleur et cette action qui sont appelés lorsque vous lancez le site web en débogue.

ValuesController : il s’agit d’un contrôleur ASP.NET Web API d’exemple. Celui-ci est composé de 5 méthodes permettant d’adresser différentes actions : récupérer une liste de valeur, récupérer une valeur par son id, ajouter une valeur, modifier une valeur, supprimer une valeur. Remarquez qu’à chacune de ces actions est associé un verbe HTTP : GET pour la récupération, POST pour l’ajout, PUT pour la modification et DELETE pour la suppression.

// GET api/values
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}

// GET api/values/5
public string Get(int id)
{
return "value";
}

// POST api/values
public void Post([FromBody]string value)
{
}

// PUT api/values/5
public void Put(int id, [FromBody]string value)
{
}

// DELETE api/values/5
public void Delete(int id)
{
}

Lancez l’application en débogue en appuyant sur F5.

Dans la barre d’adresse du navigateur, connectez-vous sur [/api/values”>http://localhost:/api/values](http://localhost:/api/values) :

image

Vous pourrez alors constater que votre navigateur vous propose de télécharger un fichier .json contenant la liste de valeurs retournées par la méthodes Get du contrôleur ValuesController, au format JSON : [“value1”,”value2”].

ASP.NET Web API utilise le même principe de routes qu’ASP.NET MVC, par défaut, toutes les URLs contenant /api/quelque chose sont redirigé vers un contrôleur de type ApiController. Ensuite, la résolution de l’action (méthode) et de ses éventuels paramètres fonctionne comme ASP.NET MVC. Le verbe HTTP utilisé est également très important puisque déterminant la méthode à appeler.

La route api par défaut est définie dans le fichier WebApiConfig du dossier** App_Start** et est initialisée dans le fichier Global.asax, au démarrage de l’application :

public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}

Création du modèle

Dans cette partie, nous allons créer le modèle chargé de représenter une requête de fonctionnalité dans l’application d’exemple. Faites un clic droit sur le dossier Models dans l’explorateur de solution et ajoutez une classe FeatureRequest :

public class FeatureRequest
{
public int Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
}

Compilez simplement l’application afin que les outils ASP.NET MVC puissent détecter cette nouvelle classe dans la suite.

Ajout d’un nouveau contrôleur Web API

Faites un clic droit sur le dossier Controllers dans l’explorateur de solution et choisissez d’ajouter un nouveau contrôleur. Dans la fenêtre qui s’ouvre, nommez le FeatureRequestsController. Dans les options de scaffholding, choisissez le template API controller with read/write actions, using Entity Framework, le Model FeatureRequest et de créer un nouveau DataContext EntityFramework pour accéder aux données :

image

Nommez votre contexte EF dans la fenêtre qui s’affiche :

image

Validez en cliquant sur OK puis Add.

Les outils ASP.NET MVC génèrent alors deux classes pour vous : FeatureRequestController.cs (dossier Controllers) et FeatureRequestWebAPIContext.cs (dossier Models). La première représente le nouveau contrôleur alors que la seconde représente le contexte Entity Framework pour l’accès aux données. Celui-ci est utilisé dans le contrôleurs, dans les différentes méthodes générées pour la récupération de la liste des requêtes, d’une requête en particulier, la création d’une requête, la modification d’une requête et enfin la suppression d’une requête.

ublic class FeatureRequestsController : ApiController
{
private FeatureRequestWebAPIContext db = new FeatureRequestWebAPIContext();

// GET api/FeatureRequests
public IEnumerable<FeatureRequest> GetFeatureRequests()
{
return db.FeatureRequests.AsEnumerable();
}

// GET api/FeatureRequests/5
public FeatureRequest GetFeatureRequest(int id)
{
FeatureRequest featurerequest = db.FeatureRequests.Find(id);
if (featurerequest == null)
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
}

return featurerequest;
}

// PUT api/FeatureRequests/5
public HttpResponseMessage PutFeatureRequest(int id, FeatureRequest featurerequest)
{
if (ModelState.IsValid && id == featurerequest.Id)
{
db.Entry(featurerequest).State = EntityState.Modified;

try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
return Request.CreateResponse(HttpStatusCode.NotFound);
}

return Request.CreateResponse(HttpStatusCode.OK);
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
}

// POST api/FeatureRequests
public HttpResponseMessage PostFeatureRequest(FeatureRequest featurerequest)
{
if (ModelState.IsValid)
{
db.FeatureRequests.Add(featurerequest);
db.SaveChanges();

HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, featurerequest);
response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = featurerequest.Id }));
return response;
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
}

// DELETE api/FeatureRequests/5
public HttpResponseMessage DeleteFeatureRequest(int id)
{
FeatureRequest featurerequest = db.FeatureRequests.Find(id);
if (featurerequest == null)
{
return Request.CreateResponse(HttpStatusCode.NotFound);
}

db.FeatureRequests.Remove(featurerequest);

try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
return Request.CreateResponse(HttpStatusCode.NotFound);
}

return Request.CreateResponse(HttpStatusCode.OK, featurerequest);
}

protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
}

Note : remarquez à nouveau que le verbe HTTP utilisé entre en jeu dans la convention de nommage des actions du contrôleur !

Si vous exécutez le site web en débogue et vous connectez à l’adresse [/api/featurerequests”>http://localhost:/api/featurerequests](http://localhost:/api/featurerequests), votre navigateur devrait vous proposer de télécharger un fichier JSON contenant la liste des requêtes de fonctionnalités (vide pour le moment, évidemment !) :

image

Conclusion

Dans cette première partie, vous avez mis en place la structure de l’application ASP.NET Web API pour la gestion des requêtes de fonctionnalités.

Dans le prochain article, nous développeront l’interface graphique qui sera en charge de consommer ce service RESTful !

A bientôt image

read more