Partager via


Itération #7 : Ajouter des fonctionnalités Ajax (C#)

par Microsoft

Télécharger le code

Dans la septième itération, nous améliorons la réactivité et les performances de notre application en ajoutant la prise en charge d’Ajax.

Génération d’une application Gestion des contacts ASP.NET MVC (C#)

Dans cette série de tutoriels, nous créons une application gestion des contacts entière du début à la fin. L’application Gestionnaire de contacts vous permet de stocker des informations de contact (noms, numéros de téléphone et adresses e-mail) pour une liste de personnes.

Nous créons l’application sur plusieurs itérations. À chaque itération, nous améliorons progressivement l’application. L’objectif de cette approche d’itération multiple est de vous permettre de comprendre la raison de chaque modification.

  • Itération n°1 - Créer l’application. Dans la première itération, nous créons le Gestionnaire de contacts de la manière la plus simple possible. Nous ajoutons la prise en charge des opérations de base de données de base : Créer, Lire, Mettre à jour et Supprimer (CRUD).

  • Itération n° 2 : rendre l’application agréable. Dans cette itération, nous améliorons l’apparence de l’application en modifiant la ASP.NET vue MVC par défaut master page et la feuille de style en cascade.

  • Itération #3 - Ajouter la validation de formulaire. Dans la troisième itération, nous ajoutons la validation de formulaire de base. Nous empêchant les utilisateurs d’envoyer un formulaire sans remplir les champs de formulaire obligatoires. Nous validons également les adresses e-mail et les numéros de téléphone.

  • Itération n° 4 : rendre l’application faiblement couplée. Dans cette quatrième itération, nous nous appuyons sur plusieurs modèles de conception de logiciels pour faciliter la maintenance et la modification de l’application Gestionnaire de contacts. Par exemple, nous refactorisons notre application pour utiliser le modèle référentiel et le modèle d’injection de dépendances.

  • Itération n°5 - Créer des tests unitaires. Dans la cinquième itération, nous rendons notre application plus facile à gérer et à modifier en ajoutant des tests unitaires. Nous nous moquons de nos classes de modèle de données et nous créons des tests unitaires pour nos contrôleurs et notre logique de validation.

  • Itération n°6 - Utiliser le développement piloté par les tests. Dans cette sixième itération, nous ajoutons de nouvelles fonctionnalités à notre application en écrivant d’abord des tests unitaires et en écrivant du code sur les tests unitaires. Dans cette itération, nous ajoutons des groupes de contacts.

  • Itération n°7 - Ajouter la fonctionnalité Ajax. Dans la septième itération, nous améliorons la réactivité et les performances de notre application en ajoutant la prise en charge d’Ajax.

Cette itération

Dans cette itération de l’application Gestionnaire de contacts, nous refactorisons notre application pour utiliser Ajax. En tirant parti d’Ajax, nous rendons notre application plus réactive. Nous pouvons éviter le rendu d’une page entière lorsque nous devons mettre à jour uniquement une certaine région d’une page.

Nous allons refactoriser notre vue Index de sorte que nous n’avons pas besoin de reliser la page entière chaque fois qu’une personne sélectionne un nouveau groupe de contacts. Au lieu de cela, quand quelqu’un clique sur un groupe de contacts, nous mettons simplement à jour la liste des contacts et laissez le reste de la page seul.

Nous allons également changer le mode de fonctionnement de notre lien de suppression. Au lieu d’afficher une page de confirmation distincte, nous allons afficher une boîte de dialogue de confirmation JavaScript. Si vous confirmez que vous souhaitez supprimer un contact, une opération HTTP DELETE est effectuée sur le serveur pour supprimer l’enregistrement de contact de la base de données.

En outre, nous allons tirer parti de jQuery pour ajouter des effets d’animation à notre vue Index. Nous allons afficher une animation lorsque la nouvelle liste de contacts est extraite du serveur.

Enfin, nous allons tirer parti de la prise en charge ASP.NET framework AJAX pour la gestion de l’historique des navigateurs. Nous allons créer des points d’historique chaque fois que nous effectuons un appel Ajax pour mettre à jour la liste des contacts. De cette façon, les boutons vers l’arrière et vers l’avant du navigateur fonctionneront.

Pourquoi utiliser Ajax ?

L’utilisation d’Ajax présente de nombreux avantages. Tout d’abord, l’ajout de fonctionnalités Ajax à une application améliore l’expérience utilisateur. Dans une application web normale, l’ensemble de la page doit être publié sur le serveur chaque fois qu’un utilisateur effectue une action. Chaque fois que vous effectuez une action, le navigateur se verrouille et l’utilisateur doit attendre que la page entière soit extraite et réaffichée.

Il s’agit d’une expérience inacceptable dans le cas d’une application de bureau. Mais, traditionnellement, nous avons vécu avec cette mauvaise expérience utilisateur dans le cas d’une application web parce que nous ne savions pas que nous pouvions faire mieux. Nous pensions qu’il s’agissait d’une limitation des applications web alors que, en réalité, c’était simplement une limitation de notre imagination.

Dans une application Ajax, vous n’avez pas besoin d’arrêter l’expérience utilisateur simplement pour mettre à jour une page. Au lieu de cela, vous pouvez effectuer une demande asynchrone en arrière-plan pour mettre à jour la page. Vous ne forcez pas l’utilisateur à attendre qu’une partie de la page soit mise à jour.

En tirant parti d’Ajax, vous pouvez également améliorer les performances de votre application. Réfléchissez au fonctionnement de l’application Gestionnaire de contacts sans la fonctionnalité Ajax. Lorsque vous cliquez sur un groupe de contacts, l’affichage Index entier doit être réaffiché. La liste des contacts et la liste des groupes de contacts doivent être récupérées à partir du serveur de base de données. Toutes ces données doivent être transmises sur le réseau du serveur web au navigateur web.

Une fois que nous avons ajouté la fonctionnalité Ajax à notre application, nous pouvons toutefois éviter de réafficher l’intégralité de la page lorsqu’un utilisateur clique sur un groupe de contacts. Nous n’avons plus besoin de récupérer les groupes de contacts de la base de données. Nous n’avons pas non plus besoin d’envoyer l’ensemble de la vue Index sur le câble. En tirant parti d’Ajax, nous réduisons la quantité de travail que notre serveur de base de données doit effectuer et nous réduisons la quantité de trafic réseau requise par notre application.

N’ayez pas peur d’Ajax

Certains développeurs évitent d’utiliser Ajax parce qu’ils se préoccupent des navigateurs de niveau inférieur. Ils veulent s’assurer que leurs applications web fonctionnent toujours lorsqu’elles sont accessibles par un navigateur qui ne prend pas en charge JavaScript. Étant donné qu’Ajax dépend de JavaScript, certains développeurs évitent d’utiliser Ajax.

Toutefois, si vous faites attention à la façon dont vous implémentez Ajax, vous pouvez créer des applications qui fonctionnent à la fois avec des navigateurs de niveau supérieur et inférieur. Notre application Gestionnaire de contacts fonctionne avec les navigateurs qui prennent en charge JavaScript et les navigateurs qui ne le font pas.

Si vous utilisez l’application Gestionnaire de contacts avec un navigateur qui prend en charge JavaScript, vous aurez une meilleure expérience utilisateur. Par exemple, lorsque vous cliquez sur un groupe de contacts, seule la région de la page qui affiche les contacts est mise à jour.

Si, en revanche, vous utilisez l’application Contact Manager avec un navigateur qui ne prend pas en charge JavaScript (ou qui a JavaScript désactivé), vous bénéficiez d’une expérience utilisateur légèrement moins souhaitable. Par exemple, lorsque vous cliquez sur un groupe de contacts, l’affichage Index entier doit être publié dans le navigateur afin d’afficher la liste correspondante des contacts.

Ajout des fichiers JavaScript requis

Nous devons utiliser trois fichiers JavaScript pour ajouter la fonctionnalité Ajax à notre application. Ces trois fichiers sont inclus dans le dossier Scripts d’une nouvelle application MVC ASP.NET.

Si vous envisagez d’utiliser Ajax dans plusieurs pages de votre application, il est judicieux d’inclure les fichiers JavaScript requis dans la vue de votre application master page. Ainsi, les fichiers JavaScript seront automatiquement inclus dans toutes les pages de votre application.

Ajoutez les éléments JavaScript suivants à l’intérieur de la <balise head> de votre page de master d’affichage :

<script src="../../Scripts/MicrosoftAjax.js" type="text/javascript"></script>
    <script src="../../Scripts/MicrosoftMvcAjax.js" type="text/javascript"></script>
    <script src="../../Scripts/jquery-1.2.6.min.js" type="text/javascript"></script>

Refactorisation de la vue Index pour utiliser Ajax

Commençons par modifier notre vue Index afin que le fait de cliquer sur un groupe de contacts ne met à jour que la région de l’affichage qui affiche les contacts. La zone rouge de la figure 1 contient la région que nous voulons mettre à jour.

Mise à jour des contacts uniquement

Figure 01 : Mise à jour des contacts uniquement (Cliquez pour afficher l’image en taille réelle)

La première étape consiste à séparer la partie de la vue que nous voulons mettre à jour de manière asynchrone en une partie distincte (afficher le contrôle utilisateur). La section de la vue Index qui affiche la table des contacts a été déplacée dans la partie de la liste 1.

Listing 1 - Views\Contact\ContactList.ascx

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ContactManager.Models.Group>" %>
<%@ Import Namespace="Helpers" %>
<table class="data-table" cellpadding="0" cellspacing="0">
    <thead>
        <tr>
            <th class="actions edit">
                Edit
            </th>
            <th class="actions delete">
                Delete
            </th>
            <th>
                Name
            </th>
            <th>
                Phone
            </th>
            <th>
                Email
            </th>
        </tr>
    </thead>
    <tbody>
        <% foreach (var item in Model.Contacts)
           { %>
        <tr>
            <td class="actions edit">
                <a href='<%= Url.Action("Edit", new {id=item.Id}) %>'><img src="../../Content/Edit.png" alt="Edit" /></a>
            </td>
            <td class="actions delete">
                <a href='<%= Url.Action("Delete", new {id=item.Id}) %>'><img src="../../Content/Delete.png" alt="Edit" /></a>
            </td>
            <th>
                <%= Html.Encode(item.FirstName) %>
                <%= Html.Encode(item.LastName) %>
            </th>
            <td>
                <%= Html.Encode(item.Phone) %>
            </td>
            <td>
                <%= Html.Encode(item.Email) %>
            </td>
        </tr>
        <% } %>
    </tbody>
</table>

Notez que le modèle partiel dans La liste 1 a un modèle différent de celui de la vue Index. L’attribut Hérite de la <directive %@ Page %> spécifie que la partie hérite de la classe de groupe> ViewUserControl<.

La vue Index mise à jour est contenue dans la liste 2.

Liste 2 - Views\Contact\Index.aspx

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<ContactManager.Models.ViewData.IndexModel>" %>
<%@ Import Namespace="Helpers" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
<title>Index</title>
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

<ul id="leftColumn">
<% foreach (var item in Model.Groups) { %>
    <li <%= Html.Selected(item.Id, Model.SelectedGroup.Id) %>>
    <%= Ajax.ActionLink(item.Name, "Index", new { id = item.Id }, new AjaxOptions { UpdateTargetId = "divContactList"})%>
    </li>
<% } %>
</ul>
<div id="divContactList">
    <% Html.RenderPartial("ContactList", Model.SelectedGroup); %>
</div>

<div class="divContactList-bottom"> </div>
</asp:Content>

Vous devez remarquer deux éléments concernant l’affichage mis à jour dans la liste 2. Tout d’abord, notez que tout le contenu déplacé dans la partie est remplacé par un appel à Html.RenderPartial(). La méthode Html.RenderPartial() est appelée lorsque la vue Index est demandée pour la première fois afin d’afficher l’ensemble initial de contacts.

Ensuite, notez que le code Html.ActionLink() utilisé pour afficher les groupes de contacts a été remplacé par ajax.ActionLink(). Ajax.ActionLink() est appelé avec les paramètres suivants :

<%= Ajax.ActionLink(item.Name, "Index", new { id = item.Id }, new AjaxOptions { UpdateTargetId = "divContactList"})%>

Le premier paramètre représente le texte à afficher pour le lien, le deuxième paramètre représente les valeurs d’itinéraire et le troisième paramètre représente les options Ajax. Dans ce cas, nous utilisons l’option UpdateTargetId Ajax pour pointer vers la balise div> HTML <que nous voulons mettre à jour une fois la demande Ajax terminée. Nous voulons mettre à jour la <balise div> avec la nouvelle liste de contacts.

La méthode Index() mise à jour du contrôleur de contacts est contenue dans la liste 3.

Listing 3 - Controllers\ContactController.cs (méthode Index)

public ActionResult Index(int? id)
{
    // Get selected group
    var selectedGroup = _service.GetGroup(id);
    if (selectedGroup == null)
        return RedirectToAction("Index", "Group");

    // Normal Request
    if (!Request.IsAjaxRequest())
    {
        var model = new IndexModel
        {
            Groups = _service.ListGroups(),
            SelectedGroup = selectedGroup
        };
        return View("Index", model);
    }

    // Ajax Request
    return PartialView("ContactList", selectedGroup);
}

L’action Index() mise à jour retourne de manière conditionnelle l’un des deux éléments suivants. Si l’action Index() est appelée par une requête Ajax, le contrôleur retourne une partie. Sinon, l’action Index() retourne une vue entière.

Notez que l’action Index() n’a pas besoin de retourner autant de données lorsqu’elle est appelée par une requête Ajax. Dans le contexte d’une requête normale, l’action Indexer retourne une liste de tous les groupes de contacts et du groupe de contacts sélectionné. Dans le contexte d’une requête Ajax, l’action Index() retourne uniquement le groupe sélectionné. Ajax signifie moins de travail sur votre serveur de base de données.

Notre vue Index modifiée fonctionne dans le cas des navigateurs de niveau supérieur et inférieur. Si vous cliquez sur un groupe de contacts et que votre navigateur prend en charge JavaScript, seule la région de l’affichage qui contient la liste des contacts est mise à jour. Si, en revanche, votre navigateur ne prend pas en charge JavaScript, la vue entière est mise à jour.

Notre vue Index mise à jour présente un problème. Lorsque vous cliquez sur un groupe de contacts, le groupe sélectionné n’est pas mis en surbrillance. Étant donné que la liste des groupes s’affiche en dehors de la région mise à jour lors d’une requête Ajax, le groupe approprié n’est pas mis en surbrillance. Nous allons résoudre ce problème dans la section suivante.

Ajout d’effets d’animation jQuery

Normalement, lorsque vous cliquez sur un lien dans une page web, vous pouvez utiliser la barre de progression du navigateur pour détecter si le navigateur extrait activement le contenu mis à jour. En revanche, lors de l’exécution d’une requête Ajax, la barre de progression du navigateur n’affiche aucune progression. Cela peut rendre les utilisateurs nerveux. Comment savoir si le navigateur est bloqué ?

Il existe plusieurs façons d’indiquer à un utilisateur que le travail est effectué lors de l’exécution d’une requête Ajax. Une approche consiste à afficher une animation simple. Par exemple, vous pouvez effacer une région lorsqu’une requête Ajax commence et la fondue dans la région à la fin de la requête.

Nous allons utiliser la bibliothèque jQuery incluse dans l’infrastructure Microsoft ASP.NET MVC pour créer les effets d’animation. La vue Index mise à jour est contenue dans la liste 4.

Liste 4 - Views\Contact\Index.aspx

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<ContactManager.Models.ViewData.IndexModel>" %>
<%@ Import Namespace="Helpers" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
<title>Index</title>
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

<script type="text/javascript">

    function beginContactList(args) {
        // Highlight selected group
        $('#leftColumn li').removeClass('selected');
        $(this).parent().addClass('selected');

        // Animate
        $('#divContactList').fadeOut('normal');
    }

    function successContactList() {
        // Animate
        $('#divContactList').fadeIn('normal');
    }

    function failureContactList() {
        alert("Could not retrieve contacts.");
    }

</script>

<ul id="leftColumn">
<% foreach (var item in Model.Groups) { %>
    <li <%= Html.Selected(item.Id, Model.SelectedGroup.Id) %>>
    <%= Ajax.ActionLink(item.Name, "Index", new { id = item.Id }, new AjaxOptions { UpdateTargetId = "divContactList", OnBegin = "beginContactList", OnSuccess = "successContactList", OnFailure = "failureContactList" })%>
    </li>
<% } %>
</ul>
<div id="divContactList">
    <% Html.RenderPartial("ContactList", Model.SelectedGroup); %>
</div>

<div class="divContactList-bottom"> </div>
</asp:Content>

Notez que la vue Index mise à jour contient trois nouvelles fonctions JavaScript. Les deux premières fonctions utilisent jQuery pour fondu et fondu dans la liste des contacts lorsque vous cliquez sur un nouveau groupe de contacts. La troisième fonction affiche un message d’erreur lorsqu’une requête Ajax génère une erreur (par exemple, délai d’attente réseau).

La première fonction s’occupe également de mettre en évidence le groupe sélectionné. Un attribut class= sélectionné est ajouté à l’élément parent (l’élément LI) de l’élément cliqué. Là encore, jQuery facilite la sélection du bon élément et l’ajout de la classe CSS.

Ces scripts sont liés aux liens de groupe à l’aide du paramètre AjaxOptions Ajax.ActionLink(). L’appel de méthode Ajax.ActionLink() mis à jour se présente comme suit :

<%= Ajax.ActionLink(item.Name, "Index", new { id = item.Id }, new AjaxOptions { UpdateTargetId = "divContactList", OnBegin = "beginContactList", OnSuccess = "successContactList", OnFailure = "failureContactList" })%>

Ajout de la prise en charge de l’historique du navigateur

Normalement, lorsque vous cliquez sur un lien pour mettre à jour une page, l’historique de votre navigateur est mis à jour. De cette façon, vous pouvez cliquer sur le bouton Précédent du navigateur pour revenir à l’état précédent de la page. Par exemple, si vous cliquez sur le groupe de contacts Amis, puis sur le groupe de contacts Professionnels, vous pouvez cliquer sur le bouton Précédent du navigateur pour revenir à l’état de la page lorsque le groupe de contacts Amis a été sélectionné.

Malheureusement, l’exécution d’une requête Ajax ne met pas à jour automatiquement l’historique du navigateur. Si vous cliquez sur un groupe de contacts et que la liste des contacts correspondants est récupérée avec une requête Ajax, l’historique du navigateur n’est pas mis à jour. Vous ne pouvez pas utiliser le bouton Précédent du navigateur pour revenir à un groupe de contacts après avoir sélectionné un nouveau groupe de contacts.

Si vous souhaitez que les utilisateurs puissent utiliser le bouton Précédent du navigateur après avoir effectué des requêtes Ajax, vous devez effectuer un peu plus de travail. Vous devez tirer parti de la fonctionnalité de gestion de l’historique des navigateurs intégrée dans le ASP.NET AJAX Framework.

ASP.NET l’historique du navigateur AJAX, vous devez effectuer trois opérations :

  1. Activez l’historique du navigateur en définissant la propriété enableBrowserHistory sur true.
  2. Enregistrez les points d’historique lorsque l’état d’une vue change en appelant la méthode addHistoryPoint().
  3. Reconstruire l’état de la vue lorsque l’événement de navigation est déclenché.

La vue Index mise à jour est contenue dans la liste 5.

Listing 5 - Views\Contact\Index.aspx

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<ContactManager.Models.ViewData.IndexModel>" %>
<%@ Import Namespace="Helpers" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
<title>Index</title>
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

<script type="text/javascript">

    var _currentGroupId = -1;

    Sys.Application.add_init(pageInit);

    function pageInit() {
        // Enable history
        Sys.Application.set_enableHistory(true);

        // Add Handler for history
        Sys.Application.add_navigate(navigate);
    }

    function navigate(sender, e) {
        // Get groupId from address bar
        var groupId = e.get_state().groupId;

        // If groupId != currentGroupId then navigate
        if (groupId != _currentGroupId) {
            _currentGroupId = groupId;
            $("#divContactList").load("/Contact/Index/" + groupId);
            selectGroup(groupId);
        }
    }

    function selectGroup(groupId) {
        $('#leftColumn li').removeClass('selected');
        if (groupId)
            $('a[groupid=' + groupId + ']').parent().addClass('selected');
        else
            $('#leftColumn li:first').addClass('selected');
    }

    function beginContactList(args) {
        // Highlight selected group
        _currentGroupId = this.getAttribute("groupid");
        selectGroup(_currentGroupId);

        // Add history point
        Sys.Application.addHistoryPoint({ "groupId": _currentGroupId });

        // Animate
        $('#divContactList').fadeOut('normal');
    }

    function successContactList() {
        // Animate
        $('#divContactList').fadeIn('normal');
    }

    function failureContactList() {
        alert("Could not retrieve contacts.");
    }

</script>

<ul id="leftColumn">
<% foreach (var item in Model.Groups) { %>
    <li <%= Html.Selected(item.Id, Model.SelectedGroup.Id) %>>
    <%= Ajax.ActionLink(item.Name, "Index", new { id = item.Id }, new AjaxOptions { UpdateTargetId = "divContactList", OnBegin = "beginContactList", OnSuccess = "successContactList", OnFailure = "failureContactList" }, new { groupid = item.Id })%>
    </li>
<% } %>
</ul>
<div id="divContactList">
    <% Html.RenderPartial("ContactList", Model.SelectedGroup); %>
</div>

<div class="divContactList-bottom"> </div>
</asp:Content>

Dans la liste 5, l’historique du navigateur est activé dans la fonction pageInit(). La fonction pageInit() est également utilisée pour configurer le gestionnaire d’événements pour l’événement de navigation. L’événement de navigation est déclenché chaque fois que le bouton Précédent ou Précédent du navigateur entraîne la modification de l’état de la page.

La méthode beginContactList() est appelée lorsque vous cliquez sur un groupe de contacts. Cette méthode crée un point d’historique en appelant la méthode addHistoryPoint(). L’ID du groupe de contacts cliqué est ajouté à l’historique.

L’ID de groupe est récupéré à partir d’un attribut expando sur le lien du groupe de contacts. Le lien est rendu avec l’appel suivant à Ajax.ActionLink().

<%= Ajax.ActionLink(item.Name, "Index", new { id = item.Id }, new AjaxOptions { UpdateTargetId = "divContactList", OnBegin = "beginContactList", OnSuccess = "successContactList", OnFailure = "failureContactList" }, new {groupid=item.Id})%>

Le dernier paramètre passé à Ajax.ActionLink() ajoute un attribut expando nommé groupid au lien (minuscules pour la compatibilité XHTML).

Lorsqu’un utilisateur clique sur le bouton Précédent ou Précédent du navigateur, l’événement de navigation est déclenché et la méthode navigate() est appelée. Cette méthode met à jour les contacts affichés dans la page pour qu’ils correspondent à l’état de la page qui correspond au point d’historique du navigateur passé à la méthode navigate.

Exécution de suppressions Ajax

Actuellement, pour supprimer un contact, vous devez cliquer sur le lien Supprimer, puis sur le bouton Supprimer affiché dans la page de confirmation de suppression (voir figure 2). Cela semble être un grand nombre de demandes de page pour effectuer quelque chose de simple, comme la suppression d’un enregistrement de base de données.

Page de confirmation de suppression

Figure 02 : Page de confirmation de suppression (Cliquer pour afficher l’image en taille réelle)

Il est tentant d’ignorer la page de confirmation de suppression et de supprimer un contact directement de la vue Index. Vous devez éviter cette tentation, car cette approche ouvre votre application aux failles de sécurité. En général, vous ne souhaitez pas effectuer une opération HTTP GET lors de l’appel d’une action qui modifie l’état de votre application web. Lorsque vous effectuez une suppression, vous souhaitez effectuer une opération HTTP POST ou, mieux encore, une opération HTTP DELETE.

Le lien Supprimer se trouve dans la partie ContactList. Une version mise à jour de la partie ContactList est contenue dans listing 6.

Listing 6 - Views\Contact\ContactList.ascx

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ContactManager.Models.Group>" %>
<%@ Import Namespace="Helpers" %>
<table class="data-table" cellpadding="0" cellspacing="0">
    <thead>
        <tr>
            <th class="actions edit">
                Edit
            </th>
            <th class="actions delete">
                Delete
            </th>
            <th>
                Name
            </th>
            <th>
                Phone
            </th>
            <th>
                Email
            </th>
        </tr>
    </thead>
    <tbody>
        <% foreach (var item in Model.Contacts)
           { %>
        <tr>
            <td class="actions edit">
                <a href='<%= Url.Action("Edit", new {id=item.Id}) %>'><img src="../../Content/Edit.png" alt="Edit" /></a>
            </td>
            <td class="actions delete">
            <%= Ajax.ImageActionLink("../../Content/Delete.png", "Delete", "Delete", new { id = item.Id }, new AjaxOptions { Confirm = "Delete contact?", HttpMethod = "Delete", UpdateTargetId = "divContactList" })%> 
            </td>
            <th>
                <%= Html.Encode(item.FirstName) %>
                <%= Html.Encode(item.LastName) %>
            </th>
            <td>
                <%= Html.Encode(item.Phone) %>
            </td>
            <td>
                <%= Html.Encode(item.Email) %>
            </td>
        </tr>
        <% } %>
    </tbody>
</table>

Le lien Delete est rendu avec l’appel suivant à la méthode Ajax.ImageActionLink() :

<%= Ajax.ImageActionLink("../../Content/Delete.png", "Delete", "Delete", new { id = item.Id }, new AjaxOptions { Confirm = "Delete contact?", HttpMethod = "Delete", UpdateTargetId = "divContactList" })%>

Notes

Ajax.ImageActionLink() n’est pas une partie standard de l’infrastructure MVC ASP.NET. Ajax.ImageActionLink() est une méthode d’assistance personnalisée incluse dans le projet Gestionnaire de contacts.

Le paramètre AjaxOptions a deux propriétés. Tout d’abord, la propriété Confirm est utilisée pour afficher une boîte de dialogue de confirmation JavaScript contextuelle. Deuxièmement, la propriété HttpMethod est utilisée pour effectuer une opération HTTP DELETE.

La liste 7 contient une nouvelle action AjaxDelete() qui a été ajoutée au contrôleur de contact.

Listing 7 - Controllers\ContactController.cs (AjaxDelete)

[AcceptVerbs(HttpVerbs.Delete)]
[ActionName("Delete")]
public ActionResult AjaxDelete(int id)
{
    // Get contact and group
    var contactToDelete = _service.GetContact(id);
    var selectedGroup = _service.GetGroup(contactToDelete.Group.Id);

    // Delete from database
    _service.DeleteContact(contactToDelete);

    // Return Contact List
    return PartialView("ContactList", selectedGroup);
}

L’action AjaxDelete() est décorée avec un attribut AcceptVerbs. Cet attribut empêche l’action d’être appelée, sauf par toute opération HTTP autre qu’une opération HTTP DELETE. En particulier, vous ne pouvez pas appeler cette action avec un HTTP GET.

Après avoir supprimé l’enregistrement de base de données, vous devez afficher la liste mise à jour des contacts qui ne contient pas l’enregistrement supprimé. La méthode AjaxDelete() renvoie la liste de contacts partielle et la liste mise à jour des contacts.

Résumé

Dans cette itération, nous avons ajouté la fonctionnalité Ajax à notre application Gestionnaire de contacts. Nous avons utilisé Ajax pour améliorer la réactivité et les performances de notre application.

Tout d’abord, nous avons refactorisé la vue Index afin que le fait de cliquer sur un groupe de contacts ne met pas à jour la vue entière. Au lieu de cela, le fait de cliquer sur un groupe de contacts met uniquement à jour la liste des contacts.

Ensuite, nous avons utilisé des effets d’animation jQuery pour fondu et fondu dans la liste des contacts. L’ajout d’animation à une application Ajax peut être utilisé pour fournir aux utilisateurs de l’application l’équivalent d’une barre de progression de navigateur.

Nous avons également ajouté la prise en charge de l’historique des navigateurs à notre application Ajax. Nous avons autorisé les utilisateurs à cliquer sur les boutons Précédent et Précédent du navigateur pour modifier l’état de la vue Index.

Enfin, nous avons créé un lien de suppression qui prend en charge les opérations HTTP DELETE. En effectuant des suppressions Ajax, nous permettons aux utilisateurs de supprimer des enregistrements de base de données sans exiger que l’utilisateur demande une page de confirmation de suppression supplémentaire.