Поделиться через


Итерация 7. Добавление функций Ajax (VB)

от Корпорации Майкрософт

Скачивание кода

В седьмой итерации мы повышаем скорость отклика и производительность приложения, добавляя поддержку Ajax.

Создание приложения управления контактами ASP.NET MVC (VB)

В этой серии учебников мы создадим все приложение "Управление контактами" от начала до конца. Приложение Диспетчер контактов позволяет хранить контактные данные ( имена, номера телефонов и адреса электронной почты) для списка людей.

Мы создаем приложение с помощью нескольких итераций. С каждой итерацией мы постепенно улучшаем приложение. Цель этого подхода с несколькими итерациями — дать возможность понять причину каждого изменения.

  • Итерация 1 — создание приложения. В первой итерации мы создадим диспетчер контактов самым простым способом. Добавлена поддержка базовых операций базы данных: создание, чтение, обновление и удаление (CRUD).

  • Итерация 2. Сделайте приложение красивым. В этой итерации мы улучшаем внешний вид приложения, изменяя ASP.NET представлении MVC по умолчанию master странице и каскадной таблице стилей.

  • Итерация 3. Добавление проверки формы. В третьей итерации мы добавим базовую проверку формы. Мы запрещаем пользователям отправлять формы без заполнения обязательных полей формы. Мы также проверяем адреса электронной почты и номера телефонов.

  • Итерация 4 . Сделайте приложение слабосвязанным. В этой четвертой итерации мы воспользуемся несколькими шаблонами проектирования программного обеспечения, чтобы упростить обслуживание и изменение приложения Диспетчера контактов. Например, мы рефакторинг приложения используем шаблон репозитория и шаблон внедрения зависимостей.

  • Итерация 5. Создание модульных тестов. В пятой итерации мы упростим обслуживание и изменение приложения путем добавления модульных тестов. Мы макетируем классы модели данных и создаем модульные тесты для контроллеров и логики проверки.

  • Итерация 6. Использование разработки на основе тестирования. В этой шестой итерации мы добавим новые функции в приложение, сначала написав модульные тесты и написав код для модульных тестов. В этой итерации мы добавим группы контактов.

  • Итерация 7 — добавление функциональных возможностей Ajax. В седьмой итерации мы повышаем скорость отклика и производительность приложения, добавляя поддержку Ajax.

Эта итерация

В этой итерации приложения Диспетчера контактов выполняется рефакторинг приложения для использования Ajax. Используя преимущества Ajax, мы делаем наше приложение более быстрым. Мы можем избежать отрисовки всей страницы, если нам нужно обновить только определенный регион на странице.

Мы рефакторингом представления индекса, чтобы не переигрывать всю страницу всякий раз, когда кто-то выбирает новую группу контактов. Вместо этого, когда кто-то щелкает группу контактов, мы просто обновим список контактов и оставим остальную часть страницы в покое.

Мы также изменим способ работы ссылки на удаление. Вместо отдельной страницы подтверждения мы отобразим диалоговое окно подтверждения JavaScript. Если вы подтверждаете, что хотите удалить контакт, на сервере выполняется операция HTTP DELETE для удаления записи контакта из базы данных.

Кроме того, мы воспользуемся преимуществами jQuery для добавления эффектов анимации в представление индекса. Анимация будет отображаться при получении нового списка контактов с сервера.

Наконец, мы воспользуемся преимуществами поддержки платформы AJAX ASP.NET для управления журналом браузера. Мы будем создавать точки журнала при каждом вызове Ajax для обновления списка контактов. Таким образом, будут работать кнопки браузера назад и вперед.

Зачем использовать Ajax?

Использование Ajax имеет множество преимуществ. Во-первых, добавление функциональных возможностей Ajax в приложение улучшает взаимодействие с пользователем. В обычном веб-приложении вся страница должна быть размещена на сервере каждый раз, когда пользователь выполняет действие. При каждом выполнении действия браузер блокируется, и пользователь должен дождаться получения и повторного воспроизведения всей страницы.

Это неприемлемо в случае с классическим приложением. Но, как правило, мы жили с этим плохим взаимодействием с пользователем в случае веб-приложения, потому что мы не знали, что мы можем сделать лучше. Мы думали, что это ограничение веб-приложений, когда, на самом деле, это просто ограничение нашего воображения.

В приложении Ajax вам не нужно останавливать пользовательский интерфейс только для обновления страницы. Вместо этого можно выполнить асинхронный запрос в фоновом режиме для обновления страницы. Вы не заставляете пользователя ждать, пока часть страницы будет обновлена.

Используя преимущества Ajax, вы также можете повысить производительность приложения. Подумайте, как приложение Диспетчера контактов работает прямо сейчас без функциональных возможностей Ajax. Щелкнув группу контактов, необходимо переиграть все представление индекса. Список контактов и список групп контактов должны быть получены с сервера базы данных. Все эти данные должны передаваться по сети от веб-сервера к веб-браузеру.

Однако после добавления функций Ajax в приложение можно избежать повторного отображения всей страницы, когда пользователь щелкает группу контактов. Нам больше не нужно захватывать группы контактов из базы данных. Нам также не нужно отправлять все представление индекса по сети. Используя преимущества Ajax, мы уменьшаем объем работы, которую должен выполнять сервер базы данных, и уменьшаем объем сетевого трафика, необходимого нашему приложению.

Не бойтесь Ajax

Некоторые разработчики не используют Ajax, так как они беспокоятся о браузерах нижнего уровня. Они хотят убедиться, что их веб-приложения по-прежнему будут работать при доступе к браузеру, который не поддерживает JavaScript. Так как Ajax зависит от JavaScript, некоторые разработчики не используют Ajax.

Тем не менее, если вы внимательно относитесь к реализации Ajax, вы можете создавать приложения, которые работают как с браузерами на более и более нижнем уровнях. Наше приложение Диспетчера контактов будет работать с браузерами, поддерживающими JavaScript, и браузерами, которые не поддерживают его.

Если вы используете приложение Диспетчера контактов с браузером, поддерживающим JavaScript, то у вас будет лучшее взаимодействие с пользователем. Например, при щелчке группы контактов обновляется только регион страницы, на котором отображаются контакты.

С другой стороны, если вы используете приложение Диспетчера контактов с браузером, который не поддерживает JavaScript (или отключен), то у вас будет немного менее желательное взаимодействие с пользователем. Например, если щелкнуть группу контактов, все представление индекса должно быть опубликовано в браузере, чтобы отобразить соответствующий список контактов.

Добавление необходимых файлов JavaScript

Для добавления функций Ajax в приложение потребуется использовать три файла JavaScript. Все три этих файла включены в папку Scripts нового приложения MVC ASP.NET.

Если вы планируете использовать Ajax на нескольких страницах в приложении, имеет смысл включить необходимые файлы JavaScript в представление приложения master страницу. Таким образом, файлы JavaScript будут включены на все страницы в приложении автоматически.

Добавьте следующий код JavaScript в <тег head> master страницы представления:

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

Рефакторинг представления индекса для использования Ajax

Начнем с изменения представления индексов, чтобы при щелчке группы контактов обновлялись только области представления, в котором отображаются контакты. Красный прямоугольник на рис. 1 содержит регион, который требуется обновить.

Обновление только контактов

Рис. 01. Обновление только контактов(Щелкните для просмотра полноразмерного изображения)

Первым шагом является разделение части представления, которую мы хотим асинхронно обновить, на отдельную часть (пользовательский элемент управления представлением). Раздел представления индекса, в котором отображается таблица контактов, был перемещен в часть в листинге 1.

Листинг 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>

Обратите внимание, что часть в листинге 1 имеет модель, отличную от модели представления индекса. Атрибут Inherits в директиве <%@ Page %> указывает, что часть наследуется от класса ViewUserControl<Group> .

Обновленное представление индекса содержится в листинге 2.

Листинг 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>

В листинге 2 об обновленном представлении следует обратить внимание на две вещи. Во-первых, обратите внимание, что все содержимое, перемещенное в часть, заменяется вызовом Html.RenderPartial(). Метод Html.RenderPartial() вызывается при первом запросе представления Индекса для отображения начального набора контактов.

Во-вторых, обратите внимание, что элемент Html.ActionLink(), используемый для отображения групп контактов, был заменен на Ajax.ActionLink(). Ajax.ActionLink() вызывается со следующими параметрами:

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

Первый параметр представляет текст, отображаемый для ссылки, второй — значения маршрута, а третий — параметры Ajax. В этом случае мы используем параметр UpdateTargetId Ajax, чтобы указать на html-тег <div> , который мы хотим обновить после завершения запроса Ajax. Мы хотим обновить <тег div> , указав новый список контактов.

Обновленный метод Index() контроллера Contact содержится в листинге 3.

Листинг 3. Controllers\ContactController.vb (метод 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

Обновленное действие Index() условно возвращает одну из двух вещей. Если действие Index() вызывается запросом Ajax, контроллер возвращает часть. В противном случае действие Index() возвращает все представление.

Обратите внимание, что действию Index() не требуется возвращать столько данных при вызове запроса Ajax. В контексте обычного запроса действие Индекс возвращает список всех групп контактов и выбранной группы контактов. В контексте запроса Ajax действие Index() возвращает только выбранную группу. Ajax означает меньшую работу на сервере базы данных.

Измененное представление индекса работает как в браузерах с более уровневым, так и с пониженным уровнями. Если щелкнуть группу контактов и браузер поддерживает JavaScript, обновляется только регион представления, содержащий список контактов. Если, с другой стороны, браузер не поддерживает JavaScript, обновляется все представление.

В обновленном представлении индексов возникла одна проблема. Щелкнув группу контактов, выбранная группа не выделяется. Так как список групп отображается за пределами региона, который обновляется во время запроса Ajax, правильная группа не выделяется. Мы исправим эту проблему в следующем разделе.

Добавление эффектов анимации jQuery

Обычно при щелчке ссылки на веб-странице можно использовать индикатор выполнения браузера, чтобы определить, активно ли браузер получает обновленное содержимое. С другой стороны, при выполнении запроса Ajax индикатор выполнения браузера не отображает ход выполнения. Это может заставить пользователей нервничать. Как узнать, завис браузер?

Существует несколько способов указать пользователю, что работа выполняется при выполнении запроса Ajax. Один из подходов заключается в отображении простой анимации. Например, вы можете выцветать регион, когда начинается запрос Ajax, и исчезать в регионе после завершения запроса.

Для создания эффектов анимации мы будем использовать библиотеку jQuery, которая входит в состав платформы Microsoft ASP.NET MVC. Обновленное представление индекса содержится в листинге 4.

Листинг 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>

Обратите внимание, что обновленное представление Индекс содержит три новые функции JavaScript. Первые две функции используют jQuery для исчезания и исчезания в списке контактов при щелчке новой группы контактов. Третья функция отображает сообщение об ошибке, когда запрос Ajax приводит к ошибке (например, время ожидания сети).

Первая функция также выполняет выделение выбранной группы. Выбранный атрибут class= добавляется к родительскому элементу (элементу LI) выбранного элемента. Опять же, jQuery позволяет легко выбрать нужный элемент и добавить класс CSS.

Эти скрипты привязаны к ссылкам групп с помощью параметра Ajax.ActionLink() AjaxOptions. Обновленный вызов метода Ajax.ActionLink() выглядит следующим образом:

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

Добавление поддержки журнала браузера

Как правило, при щелчке по ссылке для обновления страницы журнал браузера обновляется. Таким образом, вы можете нажать кнопку назад в браузере, чтобы вернуться к предыдущему состоянию страницы. Например, если щелкнуть группу контактов "Друзья", а затем выбрать группу Контактов "Бизнес", можно нажать кнопку Назад в браузере, чтобы вернуться к состоянию страницы, когда была выбрана группа контактов "Друзья".

К сожалению, выполнение запроса Ajax не обновляет журнал браузера автоматически. Если щелкнуть группу контактов и получить список соответствующих контактов с помощью запроса Ajax, журнал браузера не будет обновлен. Вы не можете использовать кнопку Назад браузера, чтобы вернуться к группе контактов после выбора новой группы контактов.

Если вы хотите, чтобы пользователи могли использовать кнопку "Назад" браузера после выполнения запросов Ajax, необходимо выполнить немного больше работы. Необходимо воспользоваться функциями управления журналами браузера, встроенными в ASP.NET AJAX Framework.

ASP.NET журнале браузера AJAX необходимо выполнить три действия.

  1. Включите журнал браузера, задав для свойства enableBrowserHistory значение true.
  2. Сохранение точек журнала при изменении состояния представления путем вызова метода addHistoryPoint().
  3. Восстановление состояния представления при возникновении события навигации.

Обновленное представление индекса содержится в листинге 5.

Листинг 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>

В листинге 5 журнал браузера включен в функции pageInit(). Функция pageInit() также используется для настройки обработчика событий для события навигации. Событие навигации возникает всякий раз, когда кнопка браузера Вперед или Назад приводит к изменению состояния страницы.

Метод beginContactList() вызывается при щелчке группы контактов. Этот метод создает новую точку журнала путем вызова метода addHistoryPoint(). Идентификатор группы контактов, нажатой, добавляется в журнал.

Идентификатор группы извлекается из атрибута expando по ссылке группы контактов. Ссылка отображается с помощью следующего вызова 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 })%>

Последний параметр, переданный в Ajax.ActionLink(), добавляет атрибут expando с именем groupid в ссылку (в нижнем регистре для совместимости XHTML).

Когда пользователь нажимает кнопку браузера Назад или Вперед, возникает событие navigate и вызывается метод navigate(). Этот метод обновляет контакты, отображаемые на странице, в соответствии с состоянием страницы, которая соответствует точке журнала браузера, переданной методу navigate.

Выполнение операций удаления Ajax

В настоящее время, чтобы удалить контакт, необходимо щелкнуть ссылку Удалить, а затем нажать кнопку Удалить, отображаемую на странице подтверждения удаления (см. рис. 2). Это похоже на много запросов страниц для выполнения простых действий, таких как удаление записи базы данных.

Страница подтверждения удаления

Рис. 02. Страница подтверждения удаления(щелкните для просмотра полноразмерного изображения)

Заманчиво пропустить страницу подтверждения удаления и удалить контакт непосредственно из представления индексов. Следует избегать этого искушения, так как такой подход открывает для приложения пробелы в безопасности. Как правило, не требуется выполнять операцию HTTP GET при вызове действия, которое изменяет состояние веб-приложения. При удалении необходимо выполнить операцию HTTP POST или, что еще лучше, операцию HTTP DELETE.

Ссылка Удалить содержится в части ContactList. Обновленная версия части ContactList содержится в листинге 6.

Листинг 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>

Ссылка Delete отображается с помощью следующего вызова метода Ajax.ImageActionLink():

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

Примечание

Ajax.ImageActionLink() не является стандартной частью платформы ASP.NET MVC. Ajax.ImageActionLink() — это настраиваемый вспомогательный метод, включенный в проект Диспетчера контактов.

Параметр AjaxOptions имеет два свойства. Во-первых, свойство Confirm используется для отображения всплывающего диалогового окна подтверждения JavaScript. Во-вторых, свойство HttpMethod используется для выполнения операции HTTP DELETE.

В листинге 7 содержится новое действие AjaxDelete(), которое было добавлено в контроллер контактов.

Листинг 7. Controllers\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

Действие AjaxDelete() украшено атрибутом AcceptVerbs. Этот атрибут предотвращает вызов действия, за исключением любой операции HTTP, отличной от операции HTTP DELETE. В частности, это действие нельзя вызвать с помощью HTTP GET.

После удаления записи базы данных необходимо отобразить обновленный список контактов, который не содержит удаленную запись. Метод AjaxDelete() возвращает часть ContactList и обновленный список контактов.

Итоги

В этой итерации мы добавили функцию Ajax в приложение Диспетчера контактов. Мы использовали Ajax для повышения скорости отклика и производительности приложения.

Во-первых, мы рефакторинговали представление Индекс, чтобы при щелчке группы контактов не обновлялось все представление. Вместо этого при выборе группы контактов обновляется только список контактов.

Затем мы использовали эффекты анимации jQuery, чтобы исчезать и исчезать в списке контактов. Добавление анимации в приложение Ajax можно использовать для предоставления пользователям приложения эквивалента индикатора выполнения браузера.

Мы также добавили поддержку журнала браузера в наше приложение Ajax. Мы позволили пользователям нажимать кнопки "Назад" и "Вперед" браузера, чтобы изменить состояние представления индекса.

Наконец, мы создали ссылку удаления, которая поддерживает операции HTTP DELETE. Благодаря удалению Ajax пользователи могут удалять записи базы данных без запроса дополнительной страницы подтверждения удаления.