Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
di Microsoft
Nella settima iterazione viene migliorata la velocità di risposta e le prestazioni dell'applicazione aggiungendo il supporto per Ajax.
Compilazione di un'applicazione MVC ASP.NET Gestione contatti (C#)
In questa serie di esercitazioni viene creata un'intera applicazione Contact Management dall'inizio alla fine. L'applicazione Contact Manager consente di archiviare le informazioni di contatto, ovvero nomi, numeri di telefono e indirizzi di posta elettronica, per un elenco di persone.
L'applicazione viene compilata su più iterazioni. Con ogni iterazione, l'applicazione viene migliorata gradualmente. L'obiettivo di questo approccio a più iterazioni è consentire di comprendere il motivo di ogni modifica.
Iterazione n. 1: creare l'applicazione. Nella prima iterazione viene creato il Contact Manager nel modo più semplice possibile. Viene aggiunto il supporto per le operazioni di base del database: Create, Read, Update e Delete (CRUD).
Iterazione n. 2: rendere l'applicazione più bella. In questa iterazione viene migliorata l'aspetto dell'applicazione modificando la pagina master della visualizzazione MVC predefinita ASP.NET e il foglio di stile css.
Iterazione n. 3: aggiungere la convalida dei moduli. Nella terza iterazione viene aggiunta la convalida dei moduli di base. Microsoft impedisce agli utenti di inviare un modulo senza completare i campi modulo obbligatori. Vengono convalidati anche gli indirizzi di posta elettronica e i numeri di telefono.
Iterazione n. 4: rendere l'applicazione ad accoppiamento 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, si esegue il refactoring dell'applicazione per usare il modello repository e il modello di inserimento delle dipendenze.
Iterazione n. 5: creare unit test. Nella quinta iterazione l'applicazione risulta più semplice da gestire e modificare aggiungendo unit test. Si simulano le classi del modello di dati e si compilano unit test per i controller e la logica di convalida.
Iterazione n. 6: usare lo sviluppo basato su test. In questa sesta iterazione si aggiungono nuove funzionalità all'applicazione scrivendo prima unit test e scrivendo codice per gli unit test. In questa iterazione si aggiungono gruppi di contatti.
Iterazione n. 7: aggiungere la funzionalità Ajax. Nella settima iterazione viene migliorata la velocità di risposta e le prestazioni dell'applicazione aggiungendo il supporto per Ajax.
Iterazione
In questa iterazione dell'applicazione Contact Manager viene refactoring dell'applicazione per usare Ajax. Sfruttando Ajax, l'applicazione è più reattiva. È possibile evitare il rendering di un'intera pagina quando è necessario aggiornare solo una determinata area in una pagina.
Verrà eseguito il refactoring della visualizzazione Indice in modo che non sia necessario rieseguire la riproduzione dell'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, aggiorneremo l'elenco dei contatti e lasceremo solo il resto della pagina.
Si modificherà anche il modo in cui funziona il collegamento di eliminazione. Invece di visualizzare una pagina di conferma separata, verrà visualizzata una finestra di dialogo di conferma javaScript. Se si conferma di voler eliminare un contatto, viene eseguita un'operazione HTTP DELETE sul server per eliminare il record di contatto dal database.
Inoltre, sfruttaremo jQuery per aggiungere effetti di animazione alla visualizzazione Indice. Verrà visualizzata un'animazione quando il nuovo elenco di contatti viene recuperato dal server.
Infine, si userà il supporto del framework ASP.NET AJAX per la gestione della cronologia del browser. I punti di cronologia verranno creati 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. Per prima cosa, l'aggiunta di funzionalità Ajax a un'applicazione comporta un'esperienza utente migliore. In una normale applicazione Web, l'intera pagina deve essere pubblicata nel server ogni volta che un utente esegue un'azione. Ogni volta che si esegue un'azione, il browser blocca e l'utente deve attendere che l'intera pagina venga recuperata e riprodotta nuovamente.
Si tratta di un'esperienza inaccettabile nel caso di un'applicazione desktop. Tuttavia, tradizionalmente, abbiamo vissuto con questa cattiva esperienza utente nel caso di un'applicazione Web perché non sapevamo che potevamo fare meglio. Abbiamo pensato che fosse una limitazione delle applicazioni Web quando, in realtà, era solo una limitazione della nostra immaginazione.
In un'applicazione Ajax non è necessario interrompere l'esperienza utente solo per aggiornare una pagina. È invece possibile eseguire una richiesta asincrona in background per aggiornare la pagina. Non forzare l'attesa dell'utente durante l'aggiornamento di parte della pagina.
Sfruttando Ajax, è anche possibile migliorare le prestazioni dell'applicazione. Considerare il funzionamento dell'applicazione Contact Manager al momento senza la funzionalità Ajax. Quando si fa clic su un gruppo di contatti, l'intera visualizzazione Indice deve essere rieseguita. 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 la rete dal server Web al Web browser.
Dopo aver aggiunto la funzionalità Ajax all'applicazione, tuttavia, è possibile evitare di riprodurre nuovamente l'intera pagina quando un utente fa clic su un gruppo di contatti. Non è più necessario acquisire i gruppi di contatti dal database. Non è inoltre necessario eseguire il push dell'intera visualizzazione Indice in transito. 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 avere paura di Ajax
Alcuni sviluppatori evitano di usare Ajax perché si preoccupano dei browser di 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 di usare Ajax.
Tuttavia, se si è attenti a come implementare Ajax, è possibile creare applicazioni che funzionano con browser di livello superiore e inferiore. L'applicazione Contact Manager funzionerà con i browser che supportano JavaScript e browser che non lo 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 in cui vengono visualizzati 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 inserita nel browser per visualizzare l'elenco di contatti corrispondente.
Aggiunta dei file JavaScript necessari
Per aggiungere funzionalità Ajax all'applicazione, è necessario usare tre file JavaScript. Tutti e tre questi file sono inclusi nella cartella Scripts di una nuova applicazione ASP.NET MVC.
Se si prevede di usare Ajax in più pagine nell'applicazione, è opportuno includere i file JavaScript necessari nella pagina master di visualizzazione dell'applicazione. In questo modo, i file JavaScript verranno inclusi automaticamente in tutte le pagine dell'applicazione.
Aggiungere il codice JavaScript seguente 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>
Effettuare il refactoring della visualizzazione indice per usare Ajax
Per iniziare, modificare 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.
Figura 01: Aggiornamento dei soli 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 una parte separata (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="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>
Si noti che la parte nell'elenco 1 ha un modello diverso rispetto alla visualizzazione Indice. L'attributo Inherits nella <direttiva %@ Page %> specifica che la proprietà parziale eredita dalla classe ViewUserControl<Group> .
La vista indice aggiornata è contenuta nell'elenco 2.
Elenco 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>
Esistono due aspetti da notare sulla visualizzazione aggiornata nell'elenco 2. In primo luogo, si noti che tutto il contenuto spostato nella parte parziale viene sostituito con una chiamata a Html.RenderPartial(). Il metodo Html.RenderPartial() viene chiamato quando viene richiesta per la prima volta la visualizzazione Index 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 Ajax.ActionLink(). Ajax.ActionLink() viene chiamato con i parametri seguenti:
<%= Ajax.ActionLink(item.Name, "Index", new { id = item.Id }, new AjaxOptions { UpdateTargetId = "divContactList"})%>
Il primo parametro rappresenta il testo da visualizzare per il collegamento, il secondo parametro rappresenta i valori di route e il terzo parametro rappresenta le opzioni Ajax. In questo caso viene usata l'opzione UpdateTargetId Ajax per puntare al tag div> HTML <che si vuole aggiornare al termine della richiesta Ajax. Si vuole aggiornare il <tag div> con il nuovo elenco di contatti.
Il metodo index() aggiornato del controller di contatto è contenuto nell'elenco 3.
Listato 3 - Controllers\ContactController.cs (metodo 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'azione Index() aggiornata restituisce in modo condizionale uno dei due elementi. 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 tutti i dati quando viene richiamata da una richiesta Ajax. Nel contesto di una richiesta normale, 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 sul server di database.
La visualizzazione Indice modificata funziona nel caso di browser di 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 che contiene l'elenco dei contatti. Se invece 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 dei 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 utilizzare la barra di stato del browser per rilevare se il browser sta recuperando attivamente il contenuto aggiornato. Quando si esegue una richiesta Ajax, invece, l'indicatore di stato del browser non mostra alcun avanzamento. Questo può rendere gli utenti nervosi. Come si sa se il browser è bloccato?
Esistono diversi modi per 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 dissolvere in dissolvenza un'area all'inizio e alla dissolvenza di una richiesta Ajax 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="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>
Si noti che la vista Indice aggiornata contiene tre nuove funzioni JavaScript. Le prime due funzioni usano jQuery per dissolversi e dissolversi 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 selezionato. 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 aggiornata al metodo Ajax.ActionLink() è simile alla seguente:
<%= Ajax.ActionLink(item.Name, "Index", new { id = item.Id }, new AjaxOptions { UpdateTargetId = "divContactList", OnBegin = "beginContactList", OnSuccess = "successContactList", OnFailure = "failureContactList" })%>
Aggiunta del supporto della 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 nel tempo allo stato precedente della pagina. Ad esempio, se si fa clic sul gruppo contatti Amici e quindi si fa clic 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 l'esecuzione di richieste Ajax, è necessario eseguire un po' di più. È necessario sfruttare le funzionalità di gestione della cronologia del browser integrate in ASP.NET AJAX Framework.
ASP.NET cronologia del browser AJAX, è necessario eseguire tre operazioni:
- Abilitare Cronologia browser impostando la proprietà enableBrowserHistory su true.
- Salvare i punti di cronologia quando lo stato di una visualizzazione cambia chiamando il metodo addHistoryPoint().
- Ricostruire lo stato della visualizzazione quando viene generato l'evento navigate.
La visualizzazione indice aggiornata è contenuta nell'elenco 5.
Elenco 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>
In Listato 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 navigate viene generato ogni volta che il pulsante Avanti o Indietro del browser determina 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 selezionato viene aggiunto alla cronologia.
L'ID gruppo viene recuperato da un attributo expando nel collegamento del gruppo di contatti. Viene eseguito il rendering del collegamento con la chiamata seguente a 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})%>
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 Indietro o Inoltra del browser, viene generato l'evento navigate e viene chiamato il metodo navigate(). Questo metodo aggiorna i contatti visualizzati nella pagina in modo che corrispondano 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). Sembra che molte richieste di pagina eseseguono operazioni semplici come l'eliminazione di un record di database.
Figura 02: Pagina di conferma dell'eliminazione (fare clic per visualizzare l'immagine a dimensione intera)
È possibile ignorare la pagina di conferma dell'eliminazione ed eliminare un contatto direttamente dalla visualizzazione Indice. È consigliabile evitare questa tentazione perché adottare questo approccio apre l'applicazione a 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'operazione HTTP POST o, meglio ancora, un'operazione HTTP DELETE.
Il collegamento Elimina è contenuto nella parte parziale di ContactList. Una versione aggiornata della parte ContactList è contenuta nell'elenco 6.
Elenco 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>
Il rendering del collegamento Delete viene eseguito con la chiamata seguente al metodo Ajax.ImageActionLink():
<%= Ajax.ImageActionLink("../../Content/Delete.png", "Delete", "Delete", new { id = item.Id }, new AjaxOptions { 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à. In primo luogo, la proprietà Confirm viene usata per visualizzare una finestra di dialogo di conferma JavaScript popup. In secondo luogo, la proprietà HttpMethod viene utilizzata per eseguire un'operazione HTTP DELETE.
L'elenco 7 contiene una nuova azione AjaxDelete() aggiunta al controller di contatto.
Elenco 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'azione AjaxDelete() è decorata con un attributo AcceptVerbs. Questo attributo impedisce che l'azione venga richiamata ad eccezione di qualsiasi operazione HTTP diversa da un'operazione HTTP DELETE. In particolare, non è possibile richiamare questa azione con HTTP GET.
Dopo aver eliminato il record del database, è necessario visualizzare l'elenco aggiornato di contatti che non contiene il record eliminato. Il metodo AjaxDelete() restituisce la proprietà 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 refactoring della visualizzazione Indice in modo che facendo clic su un gruppo di contatti non venga aggiornata l'intera visualizzazione. Al contrario, facendo clic su un gruppo di contatti viene aggiornato solo l'elenco dei contatti.
Successivamente, abbiamo usato gli effetti di animazione jQuery per dissolvere e dissolversi nell'elenco dei contatti. L'aggiunta di animazioni a un'applicazione Ajax può essere usata per fornire agli utenti dell'applicazione l'equivalente di un indicatore di stato del browser.
È stato aggiunto anche il supporto della cronologia del browser all'applicazione Ajax. Gli utenti hanno consentito agli utenti di fare clic sui pulsanti Indietro e Avanti del browser per modificare lo stato della visualizzazione Indice.
Infine, è stato creato un collegamento di eliminazione che supporta le operazioni DI ELIMINAZIONE HTTP. Eseguendo le eliminazioni Ajax, gli utenti possono eliminare i record di database senza richiedere all'utente di richiedere una pagina di conferma di eliminazione aggiuntiva.