• 30 hours
  • Medium

Free online content available in this course.

Certificate of achievement available at the end this course

You can get support and mentoring from a private teacher via videoconference on this course.

Got it!

Last updated on 11/23/17

Bonus

Log in or subscribe for free to enjoy all this course has to offer!

Nous approchons de la fin du cours. Vous commencez à connaitre beaucoup de choses d’ASP.NET MVC et vous allez désormais être capables de réaliser vos applications web. Aussi, je vous propose un dernier chapitre sous forme de bonus où je vous parlerai notamment de choses que je vous ai promis et de petites choses en plus. :)

Le squelette d’une application MVC Visual Studio

Nous avons déjà vu que nous pouvions générer dès le départ une application MVC avec déjà quelques fichiers. Il suffit d'utiliser le modèle MVC et de laisser cochée la case MVC :

Choix du modèle d'application
Choix du modèle d'application

N'hésitez pas à abuser de ce modèle, vous avez vu qu'il vous générait tout ce qu'il vous fallait pour gérer une authentification.

De même, vous avez plusieurs bundles de configurés et même la possibilité d'utiliser le filtre d'erreur et sa vue Error.cshtml (que vous retrouverez dans le répertoire Shared).

Il y a également tout un look prédéfini à base de Boostrap, qui est un framework CSS/JS créé par Twitter et qui apporte tout une palette d'outil pour la création de sites adaptatifs.

N'hésitez pas à regarder le code généré et à vous inspirer du style du site par défaut pour vous créer votre application ASP.NET MVC.

L’intérêt de l’encodage HTML

Maintenant, je voulais juste vous dire un petit mot sur la sécurité. D’une manière générale, ASP.NET MVC gère plutôt bien la sécurité, sauf qu’il peut arriver des cas où notre site peut être vulnérable et il vaut mieux y faire attention. La plus simple des attaques est ce qu’on appelle l’attaque XSS et consiste en l’injection de code malveillant dans notre page. Ce code malveillant peut simplement « déranger », mais peut également tenter de voler des informations.
Imaginons par exemple l’action de contrôleur suivante :

public ActionResult Index()
{
    ViewBag.Id = "Nico";
    return View();
}

Qui affiche la vue suivante :

<body>
    Bonjour @Html.Raw(ViewBag.Id)
</body>

Tout va bien me direz-vous… On affiche juste la phrase Bonjour Nico. Mais si jamais la chaîne est plutôt :

ViewBag.Id = "<script type=\"text/javascript\">\nalert('ahah, je t\\'ai eu !!');\n</script>";

Nous aurons sur notre page web un message disgracieux :

Un script malveillant est exécuté
Un script malveillant est exécuté

Alors OK, un petit message comme ça, ce n’est pas trop grave ; même si ça décrédibilise complètement le site. Mais nous pourrions imaginer rediriger vers une copie fallacieuse du site pour une tentative d’hameçonnage :

ViewBag.Id = "<script type=\"text/javascript\">document.location.href=\"http://fr.openclassrooms.com\";</script>";

Et voilà, vous pouvez trembler !!! Vous êtes redirigés vers le site d'OpenClassrooms. :waw:

Bon, vous allez me dire que jamais vous n’écrirez cela dans votre contrôleur… et j’espère bien ! Mais imaginez que vous affichiez quelque chose qui vienne d’un endroit pas forcément sûr, genre une base de données partagée, un service web, ou pire encore… d’une saisie utilisateur !

Alors, je vous ai beaucoup mis en garde comme quoi il ne fallait jamais faire confiance à l’utilisateur. Ce qui est vrai ! Mais vos utilisateurs ne sont pas tous des hackers en herbe qui vont essayer d’infiltrer votre système. Par contre, ils peuvent être étourdis ou simplement être réfractaire à l’informatique. Ne croyez pas que c’est parce que vous avez un champ prévu pour saisir un âge qu’ils ne vont pas, par mégarde, saisir leur prénom ou autre. C’est pour cela qu’il existe le mécanisme de validation que nous avons vu et que vous devez systématiquement vérifier ce que l’utilisateur a saisi.
Mais il peut aussi y avoir quelques utilisateurs qui s’essayent au hacking ou qui ont lu des informations sur Internet et qui vont vérifier que votre système est bien sûr.

Alors la saisie utilisateur, c’est le principal vecteur d’attaque que vous allez avoir. Sauf que d’une manière générale, il est assez difficile d’arriver à saisir des balises bizarres dans les formulaires HTML d’ASP.NET MVC car ils sont globalement protégés contre ceci. Et c’est la même chose pour les paramètres dans l’URL.
Par exemple, si vous avez votre contrôleur qui attend un id en paramètre de ce genre :

public ActionResult Index(string id)
{
    ViewBag.Id = id;
    return View();
}

Vous pourriez vous dire qu’il est très facile de mettre du JavaScript ou du HTML dedans. Mais que nenni, les URL suivantes :

  • /Home/Index?id=<h1>Youpi</h1>

  • /Home/Index?id= %3Ch1%3EYoupi%3C%2Fh1%3E

Ou tout élément du même genre produira l’erreur suivante :

Une valeur Request.QueryString potentiellement dangereuse a été détectée à partir du client (id="<h1>Youpi</h1>").

Et c’est la même chose si vous tentez de passer par un formulaire qui poste la donnée.

Alors… finalement, c’est sécurisé ? On s’en moque ?

Non pas vraiment… Déjà parce que forcément de nouvelles failles risquent d’être trouvées mais également parce qu’il y en a qui sont déjà connues. Prenez par exemple l’exemple suivant qui semble anodin :

@{
    ViewBag.Title = "Index";
}

@section scripts
{
    @if (!string.IsNullOrWhiteSpace(ViewBag.Id))
    {
        <script type="text/javascript">
            $(function () {
                var message = 'Bonjour, @ViewBag.Id';
                $("#montext").html(message).delay(1000).animate({
                    width: "70%",
                    opacity: 0.4,
                    marginLeft: "0.6in",
                    fontSize: "3em",
                    borderWidth: "10px"
                }, 1500);
            });
        </script>
    }
}
<h1 id="montext"></h1>

On se sert du JavaScript et de jQuery pour afficher le nom de l’utilisateur via une petite animation pour faire sympa.
Le code du contrôleur est tout simple :

public ActionResult Index(string id)
{
    ViewBag.Id = id;
    return View();
}

Donc, tout irait bien pour une URL de ce genre : http://localhost:49767/Home/Index/Nicolas. Mais comme nous sommes une bande de vilains hackers, nous allons tenter une autre URL. Par exemple :

http://localhost:49767/Home/Index?id=\x3cscript\x3e%20alert(\x27AHAHA\x27)%20\x3c/script\x3e

et là, c’est le drame :

Encore un script malveillant
Encore un script malveillant

Nous avons utilisé une URL avec du JavasScript encodé et nous pouvons injecter tout le code que nous voulons, et par exemple un truc un peu plus vilain qu’une boîte de message…

Alors, comment faire pour se prémunir de ce genre d’attaque ? Vous pouvez le deviner si vous avez bien lu le titre du sous-chapitre ou si vous avez été attentifs tout au long du tutoriel. Il faut encoder ce que nous écrivons dans la page. Avec le moteur de vue ASPX, il faut toujours utiliser <%: %> à la place de <%= %> et pour le moteur de vue Razor, il faut utiliser @ et pas Html.Raw(). Ah… mais c’est ce que nous avons fait et ceci fonctionne très bien pour le HTML. Mais pour le JavaScript, il faut utiliser le helper suivant @Ajax.JavaScriptStringEncode  :

var message = 'Bonjour, @Ajax.JavaScriptStringEncode(ViewBag.Id)';

Et le tour est joué.

Vous avez compris le principe. Il faut toujours encoder ce que l’on écrit dans la page, toujours vérifier les saisies de l’utilisateur, toujours se méfier… Parce que des fois, cela peut être un besoin de permettre à l’utilisateur de saisir du HTML. Imaginez par exemple des commentaires de blog, ou un forum. Il est souvent permis d’écrire du HTML pour insérer une image, un lien vers son site dans sa signature, etc. A ce moment-là, on peut désactiver la vérification du HTML d’ASP.NET MVC en décorant son modèle de l’attribut AllowHtml  :

public class MonModele
{
    public int Id { get; set; }
    [AllowHtml]
    public string DuHtml { get; set; }
}

Et là… il va falloir faire gaffe, car c’est open bar. Il faut tout encoder.
Mais en général, on fait mieux en utilisant une bibliothèque spécialisée dans la détection d’attaque. C’est le cas par exemple de la bibliothèque gratuite AntiXSS.

Il existe beaucoup d’autres attaques (je vous ai parlé également du JSON Hijacking) mais je ne vais pas vous les présenter car je ne suis pas un expert en sécurité non plus. Il est important d’être sensibilisé aux risques d’attaques, cela permet de coder en connaissance de cause. N’hésitez pas à vous documenter sur Internet.

Utiliser un « contrôle »

Je vous ai dit dans la toute première partie du cours qu’une des grandes forces d’ASP.NET WebForms est sa capacité à pouvoir réutiliser des contrôles, alors qu’avec ASP.NET MVC c’est plus délicat. Cette phrase est vraie et fausse en même temps. Il est vrai qu’il n’est pas possible d’utiliser des contrôles avec ASP.NET MVC comme on pourrait le faire avec les WebForms car il manque tout la gestion de l’état de ces contrôles, très bien prise en charge par WebForms mais inexistante avec MVC.
Par contre, ASP.NET MVC a un atout que vous connaissez déjà : les helpers. Ils permettent de simplifier l’écriture de code HTML. Et c’est presque cela que l’on demande à un contrôle web. Nous avons vu les helpers HTML, les helpers d’URL, les helpers Ajax... Je vais vous montrer ici les helpers de graphiques que l’on appelle en anglais Chart Helper .

Nous allons en profiter pour rajouter une petite touche finale complètement inutile à notre application en présentant la répartition des votes sous la forme d’un graphique.

Première chose à faire, ajouter une référence à l’assembly System.Web.Helpers. Nous allons utiliser la classe Chart . Il s’agit donc d’une classe helper qui va nous permettre de générer une image que nous pourrons afficher dans nos vues. Et pour afficher une image, on utilise bien sûr une balise HTML <img>  :

<img src="@Url.Action("AfficheGraphique", new { id = ViewBag.Id })" />

Je la mets par exemple à la fin de la vue AfficheTableau. La seule subtilité c’est que la source de l’image sera affectée à un résultat d’une action d’un contrôleur, en l’occurrence l’action AfficheGraphique du contrôleur Vote. Cela veut donc dire que la route /Vote/AfficheGraphique/1 va nous afficher une image.
Et ça, le helper de graphique sait très bien faire :

public ActionResult AfficheGraphique(int id)
{
    List<Resultats> resultats = dal.ObtenirLesResultats(id);

    Chart graphique = new Chart(width: 600, height: 400)
    .AddTitle("Résultats")
    .AddSeries(
    xValue: resultats.Select(resto => resto.Nom).ToArray(),
    yValues: resultats.Select(resto => resto.NombreDeVotes.ToString()).ToArray());
    return File(graphique.GetBytes("png"), "image/png");
}

Ici, j’indique que l’action du contrôleur me renvoie un fichier grâce à la méthode File  que nous avons déjà vue. Il s’agit d’un PNG construit grâce au helper représentant un graphique de 600x400, dont le titre est « Résultats » et qui possède en abscisses les noms des restaurants, et en ordonnées le nombres de votes :

Affichage d'un graphique avec MVC
Affichage d'un graphique avec MVC

Je ne rentrerai pas dans le détail de tout ce qu’on peut faire comme personnalisation du graphique, vous trouverez des informations sur Internet très facilement. Il y a plusieurs types de graphiques, ici j’ai choisi le graphique en barre, mais cela pourrait être un camembert, des courbes, etc. voir http://msdn.microsoft.com/fr-fr/library/dd489233.aspx.

Voilà pour l’utilisation de ce helper qui peut s’avérer bien pratique et qui nous simplifie grandement la vie. Vous vous imaginez si vous aviez dû faire tout ça tout seul ? ;)

Le routing par attribut

Le routing par attribut est une nouveauté d’ASP.NET MVC 5.
Vous vous souvenez du routing ? Mais si, on en a parlé, puis vous avez oublié. ^^ C’est la capacité de faire correspondre une URL à une méthode d’un contrôleur. Jusqu’à présent, nous avons défini la configuration de nos routes dans la classe RouteConfig, appelée par le global.asax. Cela ressemblait à :

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }
}

Eh bien si vous le souhaitez, ce temps est révolu. Vous pouvez vous simplifier la déclaration des routes en utilisant des attributs, directement sur les méthodes d’un contrôleur. Voyez plutôt :

[Route]
public ActionResult Index()
{
    return View();
}

Grâce à l’utilisation de cet attribut, vous indiquez au routing que la méthode Index du contrôleur Home correspond à une route par défaut. Et classiquement on y accède avec l’URL / ou /Home/Index. Par contre, pas par /Home, nous verrons comment y remédier…

Vous avez une autre action à mapper ? Il suffit de décorer la nouvelle méthode :

[Route("Home/Afficher")]
public ActionResult Afficher()
{
    return View();
}

Et la magie opère. Vous pouvez accéder à cette action par /Home/Afficher. Bon, quand je parle de magie, c’est un bien grand mot. Il s’agit bien sûr de code… et d’ailleurs, il faut que vous changiez du code dans le RouteConfig pour dire à ASP.NET MVC que vous voulez utiliser ce système de routing :

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapMvcAttributeRoutes();

        //routes.MapRoute(
        // name: "Default",
        // url: "{controller}/{action}/{id}",
        // defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        //);
    }
}

Je vous ai laissé ce qu’il y avait avant en commentaire. Nous rajoutons juste un appel à la méthode MapMvcAttributeRoutes  pour faire le travail.
Bien sûr, nous pouvons mettre des valeurs optionnelles dans notre route. Par exemple, pour retrouver notre fonctionnement précédent sur la méthode Index . Nous pouvons utiliser la syntaxe suivante :

[Route("{Home?}/{Index?}")]
public ActionResult Index()
{
    return View();
}

On utilise le point d’interrogation pour indiquer qu’un segment est optionnel. Ainsi nous pourrons de nouveau accéder à cette URL via / ou /Home ou /Home/Index. Le segment optionnel doit être mis entre accolades.

S’il y a conflit, alors ASP.NET MVC lèvera une erreur. Par exemple si nous définissons nos deux actions ainsi :

[Route("{Home?}/{Index?}")]
public ActionResult Index()
{
    return View();
}

[Route("{Home?}/{Afficher?}")]
public ActionResult Afficher()
{
    return View();
}

Alors nous aurons l’erreur suivante en tentant d’accéder à l’URL / :

La demande actuelle est ambiguë entre les méthodes d'action suivantes :
System.Web.Mvc.ActionResult Index() sur le type DemoAttribute.Controllers.HomeController
System.Web.Mvc.ActionResult Afficher() sur le type DemoAttribute.Controllers.HomeController

Pour passer des paramètres, rien de plus simple :

[Route("Home/Afficher/{id}")]
public ActionResult Afficher(string id)
{
    ViewBag.Id = id;
    return View();
}

qui fonctionnera par exemple avec une URL du type /Home/Afficher/Youpi. Si vous voulez avoir à traiter un entier, il suffit de changer le type du paramètre, comme avant :

[Route("Home/Afficher/{id}")]
public ActionResult Afficher(int id)
{
    ViewBag.Id = id;
    return View();
}

Ainsi, l’URL /Home/Afficher/1 fonctionnera alors que l’URL /Home/Afficher/Youpi lèvera une exception. Bien sûr, vous pouvez avoir un entier nullable, ainsi Youpi ne pourra pas être converti et id  vaudra alors null .

Nous pouvons indiquer également une valeur par défaut pour notre paramètre de cette façon :

[Route("Home/Afficher/{id=4}")]
public ActionResult Afficher(int id)
{
    ViewBag.Id = id;
    return View();
}

Ainsi, la route /Home/Afficher/ sera équivalente à /Home/Afficher/4.

Il est également possible de définir des contraintes. Par exemple, si je veux absolument que mon paramètre soit un entier, alors je peux l’indiquer comme contrainte :

[Route("Home/Afficher/{id:int}")]
public ActionResult Afficher(int id)
{
    ViewBag.Id = id;
    return View();
}

Ainsi l’URL /Home/Afficher/1 fonctionnera alors que l’URL /Home/Afficher/Youpi ne trouvera pas d’action correspondante.
Attention, c’est bien différent de ce que nous avions avant. Si le type ne collait pas avec le paramètre dans l’exemple précédent, alors il y avait une exception qui était levée. Ici, la contrainte n’est pas valide, alors l’action n’est pas éligible. Nous n’avons donc dans notre cas aucune action qui répond à cette route.

Il est souvent classique qu’un contrôleur ait ses routes qui commencent toutes par un même préfixe :

public class HomeController : Controller
{
    [Route("Home/{Index?}")]
    public ActionResult Index()
    {
        return View();
    }

    [Route("Home/Afficher/{id=4}")]
    public ActionResult Afficher(int id)
    {
        ViewBag.Id = id;
        return View();
    }

    [Route("Home/Test")]
    public ActionResult Test()
    {
        return View();
    }
}

Dans ce cas, il est possible d’utiliser un préfixe au niveau de la classe :

[RoutePrefix("Home")]
public class HomeController : Controller
{
    [Route("{Index?}")]
    public ActionResult Index()
    {
        return View();
    }

    [Route("Afficher/{id=4}")]
    public ActionResult Afficher(int id)
    {
        ViewBag.Id = id;
        return View();
    }

    [Route("Test")]
    public ActionResult Test()
    {
        return View();
    }
}

Si l’on ne veut pas utiliser le préfixe pour une méthode en particulier, on peut surcharger ce fonctionnement avec un ~ :

[Route("~/CeQueJeVeux/Afficher/{id=4}")]
public ActionResult Afficher(int id)
{
    ViewBag.Id = id;
    return View();
}

Allez, je reviens un peu sur les contraintes, en voici une liste :

Contrainte

Description

Exemple

alpha

Tous les caractères alphanumériques

{x:alpha}

bool

Un booléen

{x:bool}

datetime

Une date

{x:datetime}

decimal

Un décimal

{x:decimal}

double

Un double

{x:double}

float

Un float

{x:float}

guid

Un GUID

{x:guid}

int

Un entier

{x:int}

length

Une chaîne de la longueur souhaitée (ou dans un intervalle souhaité)

{x:length(6)}
{x:length(1,20)}

long

Un long

{x:long}

max

Un entier avec une valeur maximale

{x:max(10)}

maxlength

Une chaîne d’une longueur maximale

{x:maxlength(10)}

min

Un entier d’une valeur minimale

{x:min(10)}

minlength

Une chaîne d’une longueur minimale

{x:minlength(10)}

range

Un entier dans un intervalle

{x:range(10,50)}

regex

Une expression régulière

{x:regex(^\d{3}-\d{3}-\d{4}$)}

Il est également possible de donner un nom à une route, grâce à l’attribut Name :

[Route("{Index?}", Name = "Accueil")]
public ActionResult Index()
{
    return View();
}

Ainsi, vous pourrez générer une URL vers cette route juste grâce à son nom :

<a href="@Url.RouteUrl("Accueil")">Accueil</a>

À noter que ce système de routing est tout à fait compatible avec le précédent et nous pouvons utiliser les deux à la fois.

ASP.NET Web API

Nous sommes dans le futur, et vous avez enrichi notre application de choix de restaurant de manière à ce qu’elle soit incontournable et utilisée par beaucoup de monde. Ils vous ont réclamé une version pour mobiles et vous leur avez créé plein de vues suffixées par .Mobile de manière à ce que l’application web soit pleinement utilisable sur un appareil mobile.
Ils vous réclament maintenant une version pour Windows 8 et vous avez même l’idée de créer des applications natives événementielles sur téléphone de réalité augmentée en tirant parti de tous les capteurs de nos chers smartphones comme le gyroscope, l’accéléromètre et la caméra.

Pour ce faire, il vous faut pouvoir avoir accès à votre modèle et potentiellement à vos contrôleurs sous la forme d’API REST. Alors oui, nous savons faire en sorte que nos contrôleurs renvoient du JSON et ceci est une option tout à fait envisageable pour exposer des routes à des consommateurs mais il y a plus simple : ASP.NET Web API.
Web API est un framework basé sur ASP.NET qui est spécialisé dans la création de services HTTP de manière simple et efficace. Je ne rentrerai pas dans les détails de son utilisation, mais je vais vous montrer juste un petit exemple pour que vous puissiez voir à quoi cela sert.

Pour démarrer cet exemple, je vais commencer par créer une nouvelle application Web ASP.NET. La subtilité va être de cocher la case Web API permettant d’activer les fonctionnalités  de Web API :

Activer les fonctionnalités Web API
Activer les fonctionnalités Web API

Nous nous retrouvons avec une application web dont la structure est très proche d’une application ASP.NET MVC. Nous allons créer un modèle tout simple afin de ne pas perdre de temps dans ces bonus, mais vous pourriez tout à fait récupérer notre modèle de restaurants créé dans l’application fil rouge :

public class Resto
{
    public int Id { get; set; }
    public string Nom { get; set; }
}

public class Restos
{
    public List<Resto> ChargerRestaurants()
    {
        return new List<Resto>
        {
            new Resto { Id = 1, Nom = "Resto pinière"},
            new Resto { Id = 2, Nom = "Resto pinambour"},
            new Resto { Id = 3, Nom = "Resto ride"},
        };
    }
}

Nous allons maintenant créer un contrôleur, cela se passe de la même façon que précédemment sauf qu’il faut choisir un contrôleur Web API 2 :

Ajout d'un contrôleur Web API
Ajout d'un contrôleur Web API

Appelez-le RestaurantController et vous pouvez voir que Visual Studio nous génère une classe qui dérive de ApiController  :

public class RestaurantController : ApiController
{
}

Maintenant, rajoutez ces deux actions dans le contrôleur :

public class RestaurantController : ApiController
{
    public IEnumerable<Resto> GetTousLesRestos()
    {
        return new Restos().ChargerRestaurants();
    }

    public IHttpActionResult GetResto(int id)
    {
        Resto resto = new Restos().ChargerRestaurants().FirstOrDefault(r => r.Id == id);
        if (resto == null)
        {
            return NotFound();
        }
        return Ok(resto);
    }
}

Et c’est tout !
Nos deux contrôleurs sont accessibles via les URL suivantes :

  • http://localhost:57673/api/restaurant

  • http://localhost:57673/api/restaurant/2

Pourquoi ces routes ? Ouvrez le fichier WebApiConfig.cs qui se trouve dans le répertoire App_Start et vous comprendrez pourquoi :

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
    );

Nous retrouvons une définition de route comme avec ASP.NET MVC. Les routes sont donc par défaut /api/le_nom_du_contrôleur. En l’occurrence, notre contrôleur s’appelle Restaurant. Par contre, il n’y a pas d’action. Comment le routing instancie-t-il la bonne méthode ?
Par une convention bien sûr. Ici, en interrogeant ces deux URL, nous demandons une ressource accessible via la méthode GET du protocole HTTP. Pour trouver une action qui correspond, il suffit donc de la préfixer par Get. C’est pour ça que mes deux méthodes commencent par Get (et peu importe ce qu’on met ensuite). Si nous voulions faire une modification de ressource, nous aurions utilisé la méthode POST du protocole HTTP, et nous aurions écrit une méthode préfixée par Post…
Cette convention fonctionne également avec la méthode PUT et DELETE.
Il est également possible d’indiquer quelle est la méthode que nous souhaitons utiliser grâce à un attribut :

[HttpGet]
public IHttpActionResult TrouveResto(int id)
{
    Resto resto = new Restos().ChargerRestaurants().FirstOrDefault(r => r.Id == id);
    if (resto == null)
    {
        return NotFound();
    }
    return Ok(resto);
}

Vous me direz que ça ressemble beaucoup à du MVC, c’est le but !! :p Ce qui veut dire que vous pouvez tout à fait également changer la route pour lui dire d’utiliser l’action que vous pouvez lui fournir dans l’URL…

Je vous passe les détails de Web API car cela nécessiterait un plus long cours, mais avant de finir ce chapitre, je vais vous montrer le résultat de notre requête. Et un des meilleurs outils pour faire des requêtes REST, c’est fiddler que vous pouvez télécharger sur http://www.telerik.com/download/fiddler. Je vous passe son installation et son utilisation, si le sujet vous intéresse, n’hésitez pas à consulter des tutoriels sur le sujet.

Nous allons donc réaliser une requête Get via l’URL http://localhost:57673/api/restaurant/3 :

Requête REST en GET avec Fiddler
Requête REST en GET avec Fiddler

Le résultat, c’est du JSON :

Résultat de la requête en JSON
Résultat de la requête en JSON

C’est bien sûr le résultat de la méthode :

[HttpGet]
public IHttpActionResult TrouveResto(int id)
{
    Resto resto = new Restos().ChargerRestaurants().FirstOrDefault(r => r.Id == id);
    if (resto == null)
    {
        return NotFound();
    }
    return Ok(resto);
}

Ici, nous utilisons la méthode Ok pour renvoyer le restaurant en JSON et en même temps un code HTTP 200. Avec la méthode NotFound, nous renvoyons bien sûr un code d’erreur 404.

Remarquez que nous pouvons facilement renvoyer une liste d’éléments grâce à la méthode :

public IEnumerable<Resto> GetTousLesRestos()
{
    return new Restos().ChargerRestaurants();
}

Il suffit de renvoyer un IEnumerable (ou n’importe quel objet), et il sera automatiquement sérialisé en JSON :

[{"Id":1,"Nom":"Resto pinière"},{"Id":2,"Nom":"Resto pinambour"},{"Id":3,"Nom":"Resto ride"}]

C’est bien sûr très pratique, mais ici vous renverrez toujours un code 200 signifiant que la ressource a répondu correctement. Si pour une raison ou une autre vous voulez pouvoir renvoyer un code 404 (ou pourquoi pas un code 403 pour signifier un problème d’accès), il vous faudra repasser par la construction précédente et renvoyer un objet qui implémente IHttpActionResult .

Mais au fait, j’ai parlé uniquement de JSON dans ce chapitre car il est vrai que c’est ce format qui s’impose dans les API REST. Mais sachez qu’il est également possible d’obtenir du XML à la place du JSON et sans rien avoir à faire. Pour obtenir du XML, il suffit juste de le demander lors de notre requête et cela se fait dans les headers en précisant le header accept:application/xml  :

Requête REST pour obtenir du XML
Requête REST pour obtenir du XML

Et nous obtenons en retour :

<Resto xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/DemoWebApi.Models"><Id>3</Id><Nom>Resto ride</Nom></Resto>

Si ce header est absent, alors la valeur par défaut c’est JSON.

Voilà pour ce petit tour d’ASP.NET WEB API. Je ne vous ai pas montré grand-chose et vous pourriez vous dire que vous avez déjà bricolé des petites API REST facilement. Mais gardez à l’esprit que créer des services REST est une tâche généralement complexe dans le temps, dans la mesure où c’est ouvert au public, cela doit être sécurisé, utiliser parfaitement le protocole HTTP et gérer correctement le versionning. ASP.NET Web API gère tout ça très bien, il a été créé pour.

En résumé

  • Gardez à l’esprit que développer un site web, c’est s’exposer à de potentielles attaques. Il faut toujours se protéger et une des bases est de toujours encoder ce qui vient de valeurs pas forcément sûres.

  • Les helpers sont très pratiques pour se simplifier le développement. Le helper de graphiques permet de générer très facilement des graphiques de toutes sortes.

  • Le routing par attribut est une nouveauté d’ASP.NET MVC 5 et permet de simplifier la déclaration des routes.

  • Web API permet de réaliser très facilement des API REST.

Conclusion générale

Ça y est, vous êtes enfin arrivés au bout de ce cours. Je ne peux que vous féliciter car si vous avez été attentifs, alors vous êtes tout à fait prêt à réaliser maintenant vos propres sites web. Et c’est quasiment ce que vous avez fait avec notre magnifique application fil rouge, car vous en avez réalisé presque la totalité.

Alors qu’avons-nous fait dans ce cours ?
Nous avons déjà révisé ce qu’était un site web avec des rappels sur le HTML, le CSS et le JavaScript qui sont des langages indispensables à la réalisation de sites web. Puis nous avons découvert MVC et sa philosophie, ainsi qu’ASP.NET qui nous fournit toutes les briques dont nous avons besoin pour rendre nos sites un peu plus dynamiques.
Nous avons étudiés le modèle avec Entity Framework, la vue avec les moteurs de vues ASPX et Razor, puis le contrôleur et tout ce que l’on pouvait faire avec. Et c’est déjà beaucoup !!
Sauf que nous ne nous sommes pas arrêtés là, avides de connaissances que nous sommes, nous avons parlés de tests, de routes, d’authentification, d’Ajax… et j’en passe. Toutes ces choses vont venir se greffer à MVC pour permettre la réalisation d’applications web cohérentes et complètes.

Et tout ça, avec notre langage préféré : le C#. What Else ! :p

J’espère que ce cours a répondu à vos attentes et que vous allez continuer à créer des sites web et pourquoi pas à améliorer notre application fil rouge… Parce que c’est vrai qu’il manque des choses et qu’en plus elle n’est pas vraiment jolie. N’oubliez pas que c’est en vous entraînant que vous progresserez et que vous ne ferez plus qu’un avec ASP.NET MVC. Je n’ai pas pu vous montrer tout ASP.NET MVC non plus, mais vous avez vraiment tout ce qu’il faut pour démarrer. N’hésitez pas à consulter d’autres ressources et restez également curieux des projets communautaires qui peuvent grandement vous aider.

Bon courage et développez bien.

Example of certificate of achievement
Example of certificate of achievement