Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Le modèle Knockout MVC fait partie de ASP.NET et web Tools 2012.2
La mise à jour ASP.NET et Web Tools 2012.2 inclut un modèle d’application Single-Page (SPA) pour ASP.NET MVC 4. Ce modèle est conçu pour vous aider à créer rapidement des applications web interactives côté client.
« Application monopage » (SPA) est le terme général d’une application web qui charge une page HTML unique, puis met à jour la page dynamiquement, au lieu de charger de nouvelles pages. Après le chargement initial de la page, l’application SPA communique avec le serveur par le biais de requêtes AJAX.
AJAX n’est rien de nouveau, mais aujourd’hui, il existe des frameworks JavaScript qui facilitent la génération et la maintenance d’une grande application SPA sophistiquée. En outre, HTML 5 et CSS3 facilitent la création d’interfaces utilisateur enrichies.
Pour commencer, le modèle SPA crée un exemple d’application « Liste des tâches ». Dans ce tutoriel, nous allons suivre une visite guidée du modèle. Tout d’abord, nous allons examiner l’application de liste de tâches elle-même, puis examiner les éléments technologiques qui le rendent fonctionner.
Créer un projet de modèle SPA
Exigences:
- Visual Studio 2012 ou Visual Studio Express 2012 pour le web
- ASP.NET Web Tools 2012.2, mise à jour. Vous pouvez installer la mise à jour ici.
Démarrez Visual Studio et sélectionnez Nouveau projet dans la page De démarrage. 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, puis cliquez sur OK.
Dans l’Assistant Nouveau projet, sélectionnez Application à page unique.
Appuyez sur F5 pour générer et exécuter l’application. Lorsque l’application s’exécute pour la première fois, elle affiche un écran de connexion.
Cliquez sur le lien « S’inscrire » et créez un utilisateur.
Une fois que vous vous êtes connecté, l’application crée une liste Todo par défaut avec deux éléments. Vous pouvez cliquer sur « Ajouter une liste de tâches » pour ajouter une nouvelle liste.
Renommez la liste, ajoutez des éléments à la liste et cochez-les. Vous pouvez également supprimer des éléments ou supprimer une liste entière. Les modifications sont automatiquement conservées dans une base de données sur le serveur (en fait LocalDB à ce stade, car vous exécutez l’application localement).
Architecture du modèle SPA
Ce diagramme montre les principaux blocs de construction de l’application.
Côté serveur, ASP.NET MVC sert le code HTML et gère également l’authentification basée sur les formulaires.
ASP.NET API web gère toutes les requêtes liées aux ToDoLists et aux ToDoItems, notamment l’obtention, la création, la mise à jour et la suppression. Le client échange des données avec l’API web au format JSON.
Entity Framework (EF) est la couche O/RM. Il fait le lien entre le monde orienté objet d'ASP.NET et la base de données sous-jacente. La base de données utilise LocalDB, mais vous pouvez la modifier dans le fichier Web.config. En règle générale, vous utiliseriez LocalDB pour le développement local, puis déployez sur une base de données SQL sur le serveur, à l’aide de la migration EF code-first.
Côté client, la bibliothèque Knockout.js gère les mises à jour des pages des requêtes AJAX. Knockout utilise la liaison de données pour synchroniser la page avec les données les plus récentes. De cette façon, vous n’avez pas besoin d’écrire un code qui décrit les données JSON et met à jour le DOM. Au lieu de cela, vous placez des attributs déclaratifs dans le code HTML qui indiquent à Knockout comment présenter les données.
Un grand avantage de cette architecture est qu’elle sépare la couche de présentation de la logique d’application. Vous pouvez créer la partie API web sans connaître l’apparence de votre page web. Côté client, vous créez un « modèle d’affichage » pour représenter ces données, et le modèle de vue utilise Knockout pour établir une liaison au code HTML. Cela vous permet de modifier facilement le code HTML sans modifier le modèle d’affichage. (Nous allons regarder Knockout un peu plus tard.)
Models
Dans le projet Visual Studio, le dossier Models contient les modèles utilisés côté serveur. (Il existe également des modèles côté client ; nous y accéderons.)
TodoItem, TodoList
Il s’agit des modèles de base de données pour Entity Framework Code First. Notez que ces modèles ont des propriétés qui pointent l’un vers l’autre.
ToDoList contient une collection de ToDoItems, et chacun ToDoItem a une référence à son toDoList parent. Ces propriétés sont appelées propriétés de navigation et représentent la relation un-à-plusieurs entre une liste de tâches et ses éléments de tâches.
La ToDoItem classe utilise également l’attribut [ForeignKey] pour spécifier qu’il ToDoListId s’agit d’une clé étrangère dans la ToDoList table. Cela indique à EF d’ajouter une contrainte de clé étrangère à la base de données.
[ForeignKey("TodoList")]
public int TodoListId { get; set; }
public virtual TodoList TodoList { get; set; }
TodoItemDto, TodoListDto
Ces classes définissent les données qui seront envoyées au client. « DTO » signifie « objet de transfert de données ». Le DTO définit la façon dont les entités seront sérialisées en JSON. En général, il existe plusieurs raisons d’utiliser des DTO :
- Pour contrôler quelles propriétés sont sérialisées. Le DTO peut contenir un sous-ensemble des propriétés du modèle de domaine. Vous pouvez le faire pour des raisons de sécurité (pour masquer les données sensibles) ou simplement pour réduire la quantité de données que vous envoyez.
- Pour modifier la forme des données, par exemple pour aplatir une structure de données plus complexe.
- Pour empêcher toute logique métier hors du DTO (séparation des préoccupations).
- Si vos modèles de domaine ne peuvent pas être sérialisés pour une raison quelconque. Par exemple, les références circulaires peuvent entraîner des problèmes lorsque vous sérialisez un objet, il existe des façons de gérer ce problème dans l’API web (voir Gestion des références d’objets circulaires) ; mais l’utilisation d’un DTO évite simplement le problème.
Dans le modèle SPA, les objets de transfert de données contiennent les mêmes données que les modèles de domaine. Toutefois, ils sont toujours utiles, car ils évitent les références circulaires des propriétés de navigation et illustrent le modèle DTO général.
AccountModels.cs
Ce fichier contient des modèles pour l’appartenance au site. La UserProfile classe définit le schéma pour les profils utilisateur dans la base de données d’appartenance. (Dans ce cas, les seules informations sont l’ID utilisateur et le nom d’utilisateur.) Les autres classes de modèle de ce fichier sont utilisées pour créer les formulaires d’inscription et de connexion de l’utilisateur.
Entity Framework
Le modèle SPA utilise EF Code First. Dans le développement Code First, vous définissez d’abord les modèles dans le code, puis EF utilise le modèle pour créer la base de données. Vous pouvez également utiliser EF avec une base de données existante (Database First).
La TodoItemContext classe du dossier Models dérive de DbContext. Cette classe fournit la « colle » entre les modèles et EF.
TodoItemContext contient une collection de ToDoItem et une collection de TodoList. Pour interroger la base de données, vous écrivez simplement une requête LINQ sur ces collections. Par exemple, voici comment sélectionner toutes les listes de to-do pour l’utilisateur « Alice » :
TodoItemContext db = new TodoItemContext();
IEnumerable<TodoList> lists =
from td in db.TodoLists where td.UserId == "Alice" select td;
Vous pouvez également ajouter de nouveaux éléments à la collection, mettre à jour des éléments ou supprimer des éléments de la collection et conserver les modifications apportées à la base de données.
contrôleurs d’API web ASP.NET
Dans ASP.NET API web, les contrôleurs sont des objets qui gèrent les requêtes HTTP. Comme mentionné, le modèle SPA utilise l’API Web pour activer les opérations CRUD sur les instances ToDoList et ToDoItem. Les contrôleurs se trouvent dans le dossier Contrôleurs de la solution.
-
TodoController: gère les requêtes HTTP pour les éléments to-do -
TodoListController: gère les requêtes HTTP pour les listes de to-do.
Ces noms sont significatifs, car l’API web correspond au chemin d’URI du nom du contrôleur. (Pour savoir comment l’API web achemine les requêtes HTTP vers des contrôleurs, consultez Routage dans ASP.NET API web.)
Examinons la ToDoListController classe. Il contient un seul élément de données :
private TodoItemContext db = new TodoItemContext();
Le TodoItemContext est utilisé pour communiquer avec EF, comme décrit précédemment. Les méthodes sur le contrôleur implémentent les opérations CRUD. L’API web mappe les requêtes HTTP du client aux méthodes du contrôleur, comme suit :
| Requête HTTP | Méthode du contrôleur | Description |
|---|---|---|
| GET /api/todo | GetTodoLists |
Obtient une collection de listes de tâches. |
| GET /api/todo/id | GetTodoList |
Obtient une liste de tâches par l'ID |
| PUT /api/todo/id | PutTodoList |
Met à jour une liste de to-do. |
| POST /api/todo | PostTodoList |
Crée une nouvelle liste de tâches. |
| DELETE /api/todo/id | DeleteTodoList |
Supprime une liste de tâches. |
Notez que les URI de certaines opérations contiennent des espaces réservés pour la valeur d’ID. Par exemple, pour supprimer une liste avec un ID de 42, l’URI est /api/todo/42.
Pour en savoir plus sur l’utilisation de l’API web pour les opérations CRUD, consultez Création d’une API web prenant en charge les opérations CRUD. Le code de ce contrôleur est assez simple. Voici quelques points intéressants :
- La
GetTodoListsméthode utilise une requête LINQ pour filtrer les résultats par l’ID de l’utilisateur connecté. De cette façon, un utilisateur voit uniquement les données qui lui appartiennent. Notez également qu’une instruction Select est utilisée pour convertir lesToDoListinstances enTodoListDtoinstances. - Les méthodes PUT et POST vérifient l’état du modèle avant de modifier la base de données. Si ModelState.IsValid a la valeur false, ces méthodes retournent HTTP 400, Requête incorrecte. En savoir plus sur la validation de modèle dans l’API web lors de la validation de modèle.
- La classe de contrôleur est également décorée avec l’attribut [Authorize]. Cet attribut vérifie si la requête HTTP est authentifiée. Si la demande n’est pas authentifiée, le client reçoit HTTP 401, non autorisé. En savoir plus sur l’authentification au niveau de l’authentification et de l’autorisation dans ASP.NET API web.
La TodoController classe est très similaire à TodoListController. La plus grande différence est qu’elle ne définit aucune méthode GET, car le client obtient les éléments to-do ainsi que chaque liste de to-do.
Contrôleurs et vues MVC
Les contrôleurs MVC se trouvent également dans le dossier Contrôleurs de la solution.
HomeController affiche le code HTML principal de l’application. La vue du contrôleur d’accueil est définie dans Views/Home/Index.cshtml. La vue Accueil affiche un contenu différent selon que l’utilisateur est connecté :
@if (@User.Identity.IsAuthenticated)
{
// ....
}
Lorsque les utilisateurs sont connectés, ils voient l’interface utilisateur principale. Sinon, ils voient le panneau de connexion. Notez que ce rendu conditionnel se produit côté serveur. N’essayez jamais de masquer du contenu sensible côté client : tout ce que vous envoyez dans une réponse HTTP est visible pour quelqu’un qui surveille les messages HTTP bruts.
Client-Side JavaScript et Knockout.js
Nous allons maintenant passer du côté serveur de l’application au client. Le modèle SPA utilise une combinaison de jQuery et de Knockout.js pour créer une interface utilisateur fluide et interactive. Knockout.js est une bibliothèque JavaScript qui facilite la liaison du code HTML aux données. Knockout.js utilise un modèle appelé « Model-View-ViewModel ».
- Le modèle est les données de domaine (listes ToDo et éléments ToDo).
- La vue est le document HTML.
- Le modèle d’affichage est un objet JavaScript qui contient les données du modèle. Le modèle d’affichage est une abstraction de code de l’interface utilisateur. Il n’a aucune connaissance de la représentation HTML. Au lieu de cela, il représente des fonctionnalités abstraites de l’affichage, telles que « une liste d’éléments ToDo ».
La vue est liée aux données du modèle d’affichage. Les mises à jour du modèle d’affichage sont automatiquement reflétées dans la vue. Les liaisons fonctionnent aussi dans l’autre sens. Les événements dans le DOM (tels que les clics) sont liés aux données à des fonctions sur le modèle d’affichage, ce qui déclenche des appels AJAX.
Le modèle SPA organise le JavaScript côté client en trois couches :
- todo.datacontext.js: envoie des requêtes AJAX.
- todo.model.js: définit les modèles.
- todo.viewmodel.js: définit le modèle d’affichage.
Ces fichiers de script se trouvent dans le dossier Scripts/application de la solution.
todo.datacontext gère tous les appels AJAX aux contrôleurs d’API web. (Les appels AJAX pour la journalisation sont définis ailleurs, dans ajaxlogin.js.)
todo.model.js définit les modèles côté client (navigateur) pour les listes de to-do. Il existe deux classes de modèle : todoItem et todoList.
La plupart des propriétés des classes de modèle sont de type « ko.observable ». Les observables sont la façon dont Knockout fait sa magie. À partir de la documentation Knockout : un objet observable est un « objet JavaScript qui peut informer les abonnés des modifications ». Lorsque la valeur d’une modification observable change, Knockout met à jour tous les éléments HTML liés à ces observables. Par exemple, todoItem a des observables pour le titre et les propriétés isDone :
self.title = ko.observable(data.title);
self.isDone = ko.observable(data.isDone);
Vous pouvez également vous abonner à un objet observable dans le code. Par exemple, la classe todoItem s’abonne aux modifications apportées aux propriétés « isDone » et « title » :
saveChanges = function () {
return datacontext.saveChangedTodoItem(self);
};
// Auto-save when these properties change
self.isDone.subscribe(saveChanges);
self.title.subscribe(saveChanges);
Afficher le modèle
Le modèle d’affichage est défini dans todo.viewmodel.js. Le modèle d’affichage est le point central où l’application lie les éléments de page HTML aux données de domaine. Dans le modèle SPA, le modèle de vue contient un tableau observable de todoLists. Le code suivant dans le modèle de vue indique à Knockout d’appliquer les liaisons :
ko.applyBindings(window.todoApp.todoListViewModel);
HTML et Liaison de données
Le code HTML principal de la page est défini dans Views/Home/Index.cshtml. Étant donné que nous utilisons la liaison de données, le code HTML n’est qu’un modèle pour ce qui est réellement rendu. Knockout utilise des liaisons déclaratives . Vous liez des éléments de page aux données en ajoutant un attribut « data-bind » à l’élément. Voici un exemple très simple, tiré de la documentation Knockout :
<p>There are <span data-bind="text: myItems().count"></span> items<p>
Dans cet exemple, Knockout met à jour les contenus de l’élément <span> avec la valeur de myItems.count(). Chaque fois que cette valeur change, Knockout met à jour le document.
Knockout fournit un certain nombre de types de liaison différents. Voici quelques-unes des liaisons utilisées dans le modèle SPA :
- foreach : vous permet d’effectuer une itération dans une boucle et d’appliquer le même balisage à chaque élément de la liste. Il est utilisé pour afficher les listes de tâches et les éléments à faire. Dans la foreach, les liaisons sont appliquées aux éléments de la liste.
- visible : utilisé pour activer/désactiver la visibilité. Masquer le balisage lorsqu’une collection est vide ou rendre le message d’erreur visible.
- valeur : utilisée pour remplir les valeurs de formulaire.
- click : lie un événement click à une fonction sur le modèle d’affichage.
Anti-CSRF Protection
La falsification de requête intersites (CSRF) est une attaque où un site malveillant envoie une demande à un site vulnérable où l’utilisateur est actuellement connecté. Pour éviter les attaques CSRF, ASP.NET MVC utilise des jetons anti-falsification, également appelés jetons de vérification de demande. L’idée est que le serveur place un jeton généré de manière aléatoire dans une page web. Lorsque le client envoie des données au serveur, il doit inclure cette valeur dans le message de demande.
Les jetons anti-falsification fonctionnent car la page malveillante ne peut pas lire les jetons de l’utilisateur, en raison de stratégies de même origine. (Les stratégies de même origine empêchent les documents hébergés sur deux sites différents d’accéder au contenu de l’autre.)
ASP.NET MVC fournit une prise en charge intégrée des jetons anti-falsification, via la classe AntiForgery et l’attribut [ValidateAntiForgeryToken]. Actuellement, cette fonctionnalité n’est pas intégrée à l’API web. Toutefois, le modèle SPA inclut une implémentation personnalisée pour l’API web. Ce code est défini dans la ValidateHttpAntiForgeryTokenAttribute classe, qui se trouve dans le dossier Filtres de la solution. Pour en savoir plus sur les attaques anti-CSRF dans l’API web, consultez Prévention des attaques par falsification de requête intersites (CSRF).
Conclusion
Le modèle SPA est conçu pour vous aider à écrire rapidement des applications web modernes et interactives. Il utilise la bibliothèque Knockout.js pour séparer la présentation (balisage HTML) des données et de la logique d’application. Mais Knockout n’est pas la seule bibliothèque JavaScript que vous pouvez utiliser pour créer un spa. Si vous souhaitez explorer d’autres options, examinez les modèles SPA créés par la communauté.