Condividi tramite


Iterazione 7 - Aggiungere funzionalità Ajax (VB)

da Microsoft

Scaricare codice

Nella settima iterazione si migliora la velocità di risposta e le prestazioni dell'applicazione aggiungendo il supporto per Ajax.

Creazione di un ASP.NET applicazione MVC (VB)

In questa serie di esercitazioni viene creata un'intera applicazione Di gestione contatti dall'inizio alla fine. L'applicazione Contact Manager consente di archiviare informazioni di contatto, nomi, numeri di telefono e indirizzi di posta elettronica, per un elenco di persone.

Viene creata l'applicazione su più iterazioni. Con ogni iterazione, si migliora gradualmente l'applicazione. L'obiettivo di questo approccio a più iterazioni è quello di consentire di comprendere il motivo di ogni modifica.

  • Iterazione #1: creare l'applicazione. Nella prima iterazione, creiamo Contact Manager nel modo più semplice possibile. È possibile aggiungere il supporto per le operazioni di base del database: creare, leggere, aggiornare ed eliminare (CRUD).

  • Iterazione #2: rendere l'applicazione più bella. In questa iterazione si migliora l'aspetto dell'applicazione modificando la pagina master della visualizzazione MVC predefinita ASP.NET e il foglio di stile a catena.

  • Iterazione #3 - Aggiungere la convalida del modulo. Nella terza iterazione si aggiunge la convalida dei moduli di base. Impedisciamo agli utenti di inviare un modulo senza completare i campi del modulo obbligatori. Si convalidano anche gli indirizzi di posta elettronica e i numeri di telefono.

  • Iterazione #4: rendere l'applicazione in modo libero. In questa quarta iterazione si sfruttano diversi modelli di progettazione software per semplificare la gestione e la modifica dell'applicazione Contact Manager. Ad esempio, l'applicazione viene refactoring per usare il modello repository e il modello di inserimento delle dipendenze.

  • Iterazione #5 - Creare unit test. Nella quinta iterazione, l'applicazione semplifica la gestione e la modifica dell'applicazione aggiungendo unit test. È possibile simulare le classi del modello di dati e compilare unit test per i controller e la logica di convalida.

  • Iterazione #6 : usare lo sviluppo basato su test. In questa sesta iterazione si aggiungono nuove funzionalità all'applicazione scrivendo prima unit test e scrivendo codice rispetto agli unit test. In questa iterazione si aggiungono gruppi di contatti.

  • Iterazione 7 - Aggiungere funzionalità Ajax. Nella settima iterazione si migliora la velocità di risposta e le prestazioni dell'applicazione aggiungendo il supporto per Ajax.

Iterazione

In questa iterazione dell'applicazione Contact Manager viene refactorato l'applicazione per usare Ajax. Sfruttando Ajax, l'applicazione è più reattiva. È possibile evitare di eseguire il rendering di un'intera pagina quando è necessario aggiornare solo un'area specifica in una pagina.

Verrà eseguito il refactoring della visualizzazione Indice in modo che non sia necessario riprodurre l'intera pagina ogni volta che un utente seleziona un nuovo gruppo di contatti. Al contrario, quando un utente fa clic su un gruppo di contatti, verrà aggiornato solo l'elenco dei contatti e lasciare il resto della pagina.

Verrà inoltre modificato il modo in cui funziona il collegamento di eliminazione. Anziché visualizzare una pagina di conferma separata, verrà visualizzata una finestra di dialogo di conferma JavaScript. Se si conferma che si vuole eliminare un contatto, viene eseguita un'operazione HTTP DELETE sul server per eliminare il record di contatto dal database.

Inoltre, si sfrutta jQuery per aggiungere effetti di animazione alla visualizzazione Indice. Verrà visualizzata un'animazione quando viene recuperato il nuovo elenco di contatti dal server.

Infine, si userà il supporto del framework AJAX ASP.NET per la gestione della cronologia del browser. Verranno creati punti cronologia ogni volta che si esegue una chiamata Ajax per aggiornare l'elenco dei contatti. In questo modo, i pulsanti indietro e avanti del browser funzioneranno.

Perché usare Ajax?

L'uso di Ajax offre molti vantaggi. Prima di tutto, l'aggiunta di funzionalità Ajax a un'applicazione comporta un'esperienza utente migliore. In un'applicazione Web normale, l'intera pagina deve essere inviata al server ogni volta che un utente esegue un'azione. Ogni volta che si esegue un'azione, il browser blocca e l'utente deve attendere fino a quando l'intera pagina non viene recuperata e ricreata.

Si tratta di un'esperienza inaccettabile nel caso di un'applicazione desktop. Ma, tradizionalmente, abbiamo vissuto con questa cattiva esperienza utente nel caso di un'applicazione Web perché non sapevamo che potevamo fare meglio. Pensavamo che fosse una limitazione delle applicazioni Web quando, in realtà, era solo una limitazione delle nostre immaginazioni.

In un'applicazione Ajax non è necessario portare l'esperienza utente a un arresto solo per aggiornare una pagina. È invece possibile eseguire una richiesta asincrona in background per aggiornare la pagina. Non è necessario forzare l'attesa dell'utente durante l'aggiornamento della pagina.

Sfruttando Ajax, è anche possibile migliorare le prestazioni dell'applicazione. Si consideri come funziona l'applicazione Contact Manager subito senza funzionalità Ajax. Quando si fa clic su un gruppo di contatti, l'intera visualizzazione Indice deve essere ricreata. L'elenco dei contatti e l'elenco dei gruppi di contatti devono essere recuperati dal server di database. Tutti questi dati devono essere passati attraverso il cavo dal server Web al Web browser.

Dopo aver aggiunto la funzionalità Ajax all'applicazione, è tuttavia possibile evitare di riprodurre l'intera pagina quando un utente fa clic su un gruppo di contatti. Non è più necessario acquisire i gruppi di contatti dal database. Non è anche necessario eseguire il push dell'intera visualizzazione Indice attraverso il filo. Sfruttando Ajax, si riduce la quantità di lavoro che il server di database deve eseguire e si riduce la quantità di traffico di rete richiesto dall'applicazione.

Non aver paura di Ajax

Alcuni sviluppatori evitano di usare Ajax perché si preoccupano dei browser a livello inferiore. Vogliono assicurarsi che le applicazioni Web funzionino ancora quando si accede da un browser che non supporta JavaScript. Poiché Ajax dipende da JavaScript, alcuni sviluppatori evitano l'uso di Ajax.

Tuttavia, se si è attenti al modo in cui si implementa Ajax, è possibile creare applicazioni che funzionano con browser a livello superiore e inferiore. L'applicazione Contact Manager funzionerà con i browser che supportano JavaScript e browser che non supportano.

Se si usa l'applicazione Contact Manager con un browser che supporta JavaScript, si avrà un'esperienza utente migliore. Ad esempio, quando si fa clic su un gruppo di contatti, verrà aggiornata solo l'area della pagina che visualizza i contatti.

Se, d'altra parte, si usa l'applicazione Contact Manager con un browser che non supporta JavaScript (o che ha JavaScript disabilitato), si avrà un'esperienza utente leggermente meno auspicabile. Ad esempio, quando si fa clic su un gruppo di contatti, l'intera visualizzazione Indice deve essere pubblicata nuovamente nel browser per visualizzare l'elenco di contatti corrispondente.

Aggiunta dei file JavaScript necessari

È necessario usare tre file JavaScript per aggiungere funzionalità Ajax all'applicazione. Tutti e tre questi file sono inclusi nella cartella Script di una nuova applicazione MVC ASP.NET.

Se si prevede di usare Ajax in più pagine nell'applicazione, è consigliabile includere i file JavaScript necessari nella pagina master della visualizzazione dell'applicazione. In questo modo, i file JavaScript verranno inclusi automaticamente in tutte le pagine dell'applicazione.

Aggiungere il codice JavaScript seguente include all'interno del <tag head> della pagina master della visualizzazione:

<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>

Refactoring della visualizzazione indice per l'uso di Ajax

Iniziamo modificando la visualizzazione Indice in modo che facendo clic su un gruppo di contatti venga aggiornata solo l'area della visualizzazione che visualizza i contatti. La casella rossa nella figura 1 contiene l'area da aggiornare.

Aggiornamento solo contatti

Figura 01: Aggiornamento solo contatti(Fare clic per visualizzare l'immagine full-size)

Il primo passaggio consiste nel separare la parte della visualizzazione che si vuole aggiornare in modo asincrono in un controllo parziale separato (visualizzare il controllo utente). La sezione della visualizzazione Indice che visualizza la tabella dei contatti è stata spostata nella parte parziale nell'elenco 1.

Elenco 1 - Views\Contact\ContactList.ascx

<%@ Control Language="VB" Inherits="System.Web.Mvc.ViewUserControl(Of ContactManager.Group)" %>
<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>
        <% For Each item in Model.Contacts %>
        <tr>
            <td class="actions edit">
                <a href='<%= Url.Action("Edit", New With {.id=item.Id}) %>'><img src="../../Content/Edit.png" alt="Edit" /></a>
            </td>
            <td class="actions delete">
                <a href='<%= Url.Action("Delete", New With {.id=item.Id}) %>'><img src="../../Content/Delete.png" alt="Delete" /></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>
        <% Next %>
    </tbody>
</table>

Si noti che il parziale nell'elenco 1 ha un modello diverso rispetto alla visualizzazione Indice. L'attributo Eredita nella <direttiva %@ Page %> specifica che il valore parziale eredita dalla classe ViewUserControl<Group> .

La visualizzazione indice aggiornata è contenuta nell'elenco 2.

Elenco 2 - Views\Contact\Index.aspx

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

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

<ul id="leftColumn">
<% For Each item in Model.Groups %>
    <li <%= Html.Selected(item.Id, Model.SelectedGroup.Id) %>>
    <%= Ajax.ActionLink(item.Name, "Index", New With { .id = item.Id }, New AjaxOptions With { .UpdateTargetId = "divContactList"})%>
    </li>
<% Next %>
</ul>
<div id="divContactList">
    <% Html.RenderPartial("ContactList", Model.SelectedGroup) %>
</div>

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

Esistono due elementi che si dovrebbero notare sulla visualizzazione aggiornata nell'elenco 2. Prima di tutto, si noti che tutto il contenuto spostato nel parziale viene sostituito con una chiamata a Html.RenderPartial(). Il metodo Html.RenderPartial() viene chiamato quando la visualizzazione Index viene richiesta per la prima volta per visualizzare il set iniziale di contatti.

In secondo luogo, si noti che html.ActionLink() usato per visualizzare i gruppi di contatti è stato sostituito con un Ajax.ActionLink(). Ajax.ActionLink() viene chiamato con i parametri seguenti:

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

Il primo parametro rappresenta il testo da visualizzare per il collegamento, il secondo parametro rappresenta i valori della route e il terzo parametro rappresenta le opzioni Ajax. In questo caso, si usa l'opzione UpdateTargetId Ajax per puntare al tag div> HTML <che si vuole aggiornare dopo il completamento della richiesta Ajax. Si vuole aggiornare il <tag div> con il nuovo elenco di contatti.

Il metodo Index() aggiornato del controller Contact è contenuto nell'elenco 3.

Elenco 3 - Controller\ContactController.vb (metodo Index)

Public Function Index(ByVal id As Integer?) As ActionResult
    ' Get selected group
    Dim selectedGroup = _service.GetGroup(id)
    if IsNothing(selectedGroup) Then
        Return RedirectToAction("Index", "Group")
    End If

    ' Normal Request
    if Not Request.IsAjaxRequest() Then
        Dim model As new IndexModel With { _
            .Groups = _service.ListGroups(), _
            .SelectedGroup = selectedGroup _
        }
        Return View("Index", model)
    End If

    ' Ajax Request
    return PartialView("ContactList", selectedGroup)
End Function

L'azione Index() aggiornata restituisce una delle due cose. Se l'azione Index() viene richiamata da una richiesta Ajax, il controller restituisce un valore parziale. In caso contrario, l'azione Index() restituisce un'intera visualizzazione.

Si noti che l'azione Index() non deve restituire quanti dati quando viene richiamata da una richiesta Ajax. Nel contesto di una normale richiesta, l'azione Index restituisce un elenco di tutti i gruppi di contatti e del gruppo di contatti selezionato. Nel contesto di una richiesta Ajax, l'azione Index() restituisce solo il gruppo selezionato. Ajax significa meno lavoro nel server di database.

La visualizzazione Indice modificato funziona nel caso di browser a livello superiore e inferiore. Se si fa clic su un gruppo di contatti e il browser supporta JavaScript, viene aggiornata solo l'area della visualizzazione contenente l'elenco di contatti. Se, d'altra parte, il browser non supporta JavaScript, l'intera visualizzazione viene aggiornata.

La visualizzazione indice aggiornata presenta un problema. Quando si fa clic su un gruppo di contatti, il gruppo selezionato non è evidenziato. Poiché l'elenco di gruppi viene visualizzato all'esterno dell'area aggiornata durante una richiesta Ajax, il gruppo corretto non viene evidenziato. Questo problema verrà risolto nella sezione successiva.

Aggiunta di effetti di animazione jQuery

In genere, quando si fa clic su un collegamento in una pagina Web, è possibile usare la barra di stato del browser per rilevare se il browser recupera attivamente il contenuto aggiornato. Quando si esegue una richiesta Ajax, invece, la barra di stato del browser non mostra alcun stato di avanzamento. Questo può rendere gli utenti nervosi. Come si sa se il browser ha bloccato?

Esistono diversi modi in cui è possibile indicare a un utente che il lavoro viene eseguito durante l'esecuzione di una richiesta Ajax. Un approccio consiste nel visualizzare un'animazione semplice. Ad esempio, è possibile sadere un'area quando una richiesta Ajax inizia e sade nell'area al termine della richiesta.

Verrà usata la libreria jQuery inclusa nel framework Microsoft ASP.NET MVC per creare gli effetti di animazione. La visualizzazione indice aggiornata è contenuta nell'elenco 4.

Elenco 4 - Views\Contact\Index.aspx

<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage(Of ContactManager.IndexModel)" %>
<%@ Import Namespace="ContactManager" %>
<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">
<% For Each item in Model.Groups %>
    <li <%= Html.Selected(item.Id, Model.SelectedGroup.Id) %>>
    <%= Ajax.ActionLink(item.Name, "Index", New With { .id = item.Id }, New AjaxOptions With { .UpdateTargetId = "divContactList", .OnBegin = "beginContactList", .OnSuccess = "successContactList", .OnFailure = "failureContactList" })%>
    </li>
<% Next %>
</ul>
<div id="divContactList">
    <% Html.RenderPartial("ContactList", Model.SelectedGroup) %>
</div>

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

Si noti che la visualizzazione indice aggiornata contiene tre nuove funzioni JavaScript. Le prime due funzioni usano jQuery per sadere e sadere nell'elenco dei contatti quando si fa clic su un nuovo gruppo di contatti. La terza funzione visualizza un messaggio di errore quando una richiesta Ajax genera un errore (ad esempio, timeout di rete).

La prima funzione si occupa anche dell'evidenziazione del gruppo selezionato. Un attributo class= selezionato viene aggiunto all'elemento padre (l'elemento LI) dell'elemento fatto clic. Anche in questo caso, jQuery semplifica la selezione dell'elemento destro e l'aggiunta della classe CSS.

Questi script sono associati ai collegamenti di gruppo con l'aiuto del parametro Ajax.ActionLink() AjaxOptions. La chiamata al metodo Ajax.ActionLink() aggiornata è simile alla seguente:

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

Aggiunta del supporto per la cronologia del browser

In genere, quando si fa clic su un collegamento per aggiornare una pagina, la cronologia del browser viene aggiornata. In questo modo, è possibile fare clic sul pulsante Indietro del browser per tornare indietro nello stato precedente della pagina. Ad esempio, se si fa clic sul gruppo di contatti Amici e quindi sul gruppo contatti business, è possibile fare clic sul pulsante Indietro del browser per tornare allo stato della pagina quando è stato selezionato il gruppo di contatti Amici.

Sfortunatamente, l'esecuzione di una richiesta Ajax non aggiorna automaticamente la cronologia del browser. Se si fa clic su un gruppo di contatti e l'elenco dei contatti corrispondenti viene recuperato con una richiesta Ajax, la cronologia del browser non viene aggiornata. Non è possibile usare il pulsante Indietro del browser per tornare a un gruppo di contatti dopo aver selezionato un nuovo gruppo di contatti.

Se si vuole che gli utenti possano usare il pulsante Indietro del browser dopo aver eseguito richieste Ajax, è necessario eseguire un po' di lavoro. È necessario sfruttare le funzionalità di gestione della cronologia del browser compilate nel ASP.NET AJAX Framework.

ASP.NET cronologia del browser AJAX, è necessario eseguire tre operazioni:

  1. Abilitare Cronologia browser impostando la proprietà enableBrowserHistory su true.
  2. Salvare i punti di cronologia quando lo stato di una visualizzazione viene modificato chiamando il metodo addHistoryPoint().
  3. Ricostruire lo stato della visualizzazione quando viene generato l'evento di navigazione.

La visualizzazione indice aggiornata è contenuta nell'elenco 5.

Elenco 5 - Views\Contact\Index.aspx

<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage(Of ContactManager.IndexModel)" %>
<%@ Import Namespace="ContactManager" %>
<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">
<% For Each item in Model.Groups %>
    <li <%= Html.Selected(item.Id, Model.SelectedGroup.Id) %>>
    <%= Ajax.ActionLink(item.Name, "Index", New With { .id = item.Id }, New AjaxOptions With { .UpdateTargetId = "divContactList", .OnBegin = "beginContactList", .OnSuccess = "successContactList", .OnFailure = "failureContactList" }, New With { .groupid = item.Id })%>
    </li>
<% Next %>
</ul>
<div id="divContactList">
    <% Html.RenderPartial("ContactList", Model.SelectedGroup) %>
</div>

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

In Elenco 5, la cronologia del browser è abilitata nella funzione pageInit(). La funzione pageInit() viene usata anche per configurare il gestore eventi per l'evento navigate. L'evento di navigazione viene generato ogni volta che il pulsante Avanti o Indietro del browser causa la modifica dello stato della pagina.

Il metodo beginContactList() viene chiamato quando si fa clic su un gruppo di contatti. Questo metodo crea un nuovo punto di cronologia chiamando il metodo addHistoryPoint(). L'ID del gruppo di contatti fatto clic su viene aggiunto alla cronologia.

L'ID gruppo viene recuperato da un attributo expando nel collegamento del gruppo di contatti. Il rendering del collegamento viene eseguito con la chiamata seguente a Ajax.ActionLink().

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

L'ultimo parametro passato a Ajax.ActionLink() aggiunge un attributo expando denominato groupid al collegamento (minuscolo per la compatibilità XHTML).

Quando un utente raggiunge il pulsante Back o Forward del browser, viene generato l'evento navigate e viene chiamato il metodo navigate(). Questo metodo aggiorna i contatti visualizzati nella pagina per corrispondere allo stato della pagina corrispondente al punto di cronologia del browser passato al metodo navigate.

Esecuzione di eliminazioni Ajax

Attualmente, per eliminare un contatto, è necessario fare clic sul collegamento Elimina e quindi fare clic sul pulsante Elimina visualizzato nella pagina di conferma dell'eliminazione (vedere la figura 2). Questo sembra un sacco di richieste di pagina per eseguire operazioni semplici come l'eliminazione di un record di database.

Pagina di conferma dell'eliminazione

Figura 02: Pagina di conferma dell'eliminazione(Fare clic per visualizzare l'immagine full-size)

È tentato di ignorare la pagina di conferma dell'eliminazione ed eliminare un contatto direttamente dalla visualizzazione Indice. È consigliabile evitare questa tentazione perché l'approccio apre l'applicazione ai fori di sicurezza. In generale, non si vuole eseguire un'operazione HTTP GET quando si richiama un'azione che modifica lo stato dell'applicazione Web. Quando si esegue un'eliminazione, si vuole eseguire un POST HTTP o, meglio, un'operazione HTTP DELETE.

Il collegamento Elimina è contenuto nella parte di ContactList. Una versione aggiornata della parte ContactList è contenuta nell'elenco 6.

Elenco 6 - Views\Contact\ContactList.ascx

<%@ Control Language="VB" Inherits="System.Web.Mvc.ViewUserControl(Of ContactManager.Group)" %>
<%@ Import Namespace="ContactManager" %>
<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>
        <% For Each item in Model.Contacts %>
        <tr>
            <td class="actions edit">
                <a href='<%= Url.Action("Edit", New With {.id=item.Id}) %>'><img src="../../Content/Edit.png" alt="Edit" /></a>
            </td>
            <td class="actions delete">
                <%= Ajax.ImageActionLink("../../Content/Delete.png", "Delete", "Delete", New with { .id = item.Id }, New AjaxOptions With { .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>
        <% Next %>
    </tbody>
</table>

Il collegamento Delete viene eseguito il rendering con la chiamata seguente al metodo Ajax.ImageActionLink():

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

Nota

Ajax.ImageActionLink() non è una parte standard del framework MVC ASP.NET. Ajax.ImageActionLink() è un metodo helper personalizzato incluso nel progetto Contact Manager.

Il parametro AjaxOptions ha due proprietà. Prima di tutto, la proprietà Confirm viene usata per visualizzare una finestra di dialogo di conferma JavaScript popup. In secondo luogo, la proprietà HttpMethod viene usata per eseguire un'operazione HTTP DELETE.

L'elenco 7 contiene una nuova azione AjaxDelete() aggiunta al controller di contatto.

Elenco 7 - Controller\ContactController.vb (AjaxDelete)

<AcceptVerbs(HttpVerbs.Delete), ActionName("Delete")> _
Public Function AjaxDelete(ByVal id As Integer) As ActionResult
    ' Get contact and group
    Dim contactToDelete = _service.GetContact(id)
    Dim selectedGroup = _service.GetGroup(contactToDelete.Group.Id)

    ' Delete from database
    _service.DeleteContact(contactToDelete)

    ' Return Contact List
    Return PartialView("ContactList", selectedGroup)
End Function

L'azione AjaxDelete() viene decorata con un attributo AcceptVerbs. Questo attributo impedisce che l'azione venga richiamata tranne da qualsiasi operazione HTTP diversa da un'operazione HTTP DELETE. In particolare, non è possibile richiamare questa azione con UN GET HTTP.

Dopo aver eliminato il record del database, è necessario visualizzare l'elenco aggiornato di contatti che non contengono il record eliminato. Il metodo AjaxDelete() restituisce il parametro ContactList parziale e l'elenco aggiornato dei contatti.

Riepilogo

In questa iterazione è stata aggiunta la funzionalità Ajax all'applicazione Contact Manager. È stato usato Ajax per migliorare la velocità di risposta e le prestazioni dell'applicazione.

Prima di tutto, è stato refactorato la visualizzazione Indice in modo che facendo clic su un gruppo di contatti non venga aggiornata l'intera visualizzazione. Fare invece clic su un gruppo di contatti aggiorna solo l'elenco dei contatti.

Successivamente, abbiamo usato gli effetti di animazione jQuery per sadere e sadere nell'elenco dei contatti. L'aggiunta di animazioni a un'applicazione Ajax può essere usata per fornire agli utenti dell'applicazione l'equivalente di una barra di stato del browser.

È stato aggiunto anche il supporto della cronologia del browser all'applicazione Ajax. Gli utenti hanno abilitato a fare clic sui pulsanti Indietro e Avanti del browser per modificare lo stato della visualizzazione Indice.

È stato infine creato un collegamento di eliminazione che supporta le operazioni HTTP DELETE. Eseguendo eliminazioni Ajax, gli utenti possono eliminare i record del database senza richiedere all'utente una pagina di conferma aggiuntiva per l'eliminazione.