Udostępnij za pośrednictwem


Iteracja 7 — Dodawanie funkcji Ajax (VB)

autor: Microsoft

Pobierz kod

W siódmej iteracji poprawiamy czas reakcji i wydajność naszej aplikacji, dodając obsługę Ajax.

Tworzenie ASP.NET aplikacji MVC do zarządzania kontaktami (VB)

W tej serii samouczków utworzymy całą aplikację do zarządzania kontaktami od początku do końca. Aplikacja Contact Manager umożliwia przechowywanie informacji kontaktowych — nazw, numerów telefonów i adresów e-mail — dla listy osób.

Tworzymy aplikację za pośrednictwem wielu iteracji. Po każdej iteracji stopniowo ulepszamy aplikację. Celem tego podejścia iteracji wielokrotnej jest umożliwienie zrozumienia przyczyny każdej zmiany.

  • Iteracja #1 — tworzenie aplikacji. W pierwszej iteracji utworzymy menedżera kontaktów w najprostszy możliwy sposób. Dodamy obsługę podstawowych operacji bazy danych: tworzenie, odczytywanie, aktualizowanie i usuwanie (CRUD).

  • Iteracja #2 — sprawia, że aplikacja wygląda ładnie. W tej iteracji poprawiamy wygląd aplikacji, modyfikując domyślną stronę wzorcową ASP.NET widoku MVC i kaskadowy arkusz stylów.

  • Iteracja #3 — dodawanie walidacji formularza. W trzeciej iteracji dodamy podstawową walidację formularza. Uniemożliwiamy użytkownikom przesyłanie formularza bez wypełniania wymaganych pól formularza. Weryfikujemy również adresy e-mail i numery telefonów.

  • Iteracja #4 — luźno połącz aplikację. W tej czwartej iteracji korzystamy z kilku wzorców projektowania oprogramowania, aby ułatwić konserwację i modyfikowanie aplikacji Contact Manager. Na przykład refaktoryzujemy naszą aplikację, aby używać wzorca repozytorium i wzorca wstrzykiwania zależności.

  • Iteracja #5 — tworzenie testów jednostkowych. W piątej iteracji ułatwiamy konserwację i modyfikowanie aplikacji przez dodanie testów jednostkowych. Wyśmiewamy nasze klasy modelu danych i kompilujemy testy jednostkowe dla naszych kontrolerów i logiki walidacji.

  • Iteracja nr 6 — korzystanie z programowania opartego na testach. W tej szóstej iteracji dodamy nową funkcjonalność do naszej aplikacji, pisząc najpierw testy jednostkowe i pisząc kod względem testów jednostkowych. W tej iteracji dodajemy grupy kontaktów.

  • Iteracja #7 — dodawanie funkcji Ajax. W siódmej iteracji poprawiamy czas reakcji i wydajność naszej aplikacji, dodając obsługę Ajax.

Ta iteracja

W tej iteracji aplikacji Contact Manager refaktoryzujemy naszą aplikację, aby korzystać z Ajax. Korzystając z technologii Ajax, nasza aplikacja jest bardziej elastyczna. Możemy uniknąć renderowania całej strony, gdy musimy zaktualizować tylko określony region na stronie.

Refaktoryzujemy nasz widok indeksu, aby nie trzeba było redisplay całej strony za każdym razem, gdy ktoś wybierze nową grupę kontaktów. Zamiast tego, gdy ktoś kliknie grupę kontaktów, po prostu zaktualizujemy listę kontaktów i pozostawimy pozostałą część strony.

Zmienimy również sposób działania linku usuwania. Zamiast wyświetlać oddzielną stronę potwierdzenia, zostanie wyświetlone okno dialogowe potwierdzenia języka JavaScript. Jeśli potwierdzisz, że chcesz usunąć kontakt, operacja HTTP DELETE jest wykonywana względem serwera w celu usunięcia rekordu kontaktu z bazy danych.

Ponadto skorzystamy z funkcji jQuery, aby dodać efekty animacji do widoku indeksu. Zostanie wyświetlona animacja po pobraniu nowej listy kontaktów z serwera.

Na koniec skorzystamy z obsługi platformy ASP.NET AJAX do zarządzania historią przeglądarki. Utworzymy punkty historii za każdym razem, gdy wykonamy wywołanie Ajax, aby zaktualizować listę kontaktów. W ten sposób przyciski do tyłu i do przodu przeglądarki będą działać.

Dlaczego warto używać Ajax?

Korzystanie z Ajax ma wiele korzyści. Najpierw dodanie funkcji Ajax do aplikacji powoduje lepsze środowisko użytkownika. W normalnej aplikacji internetowej cała strona musi zostać wysłana z powrotem do serwera za każdym razem, gdy użytkownik wykonuje akcję. Za każdym razem, gdy wykonujesz akcję, przeglądarka zostanie zablokowana, a użytkownik musi poczekać, aż cała strona zostanie pobrana i odtworzona.

Byłoby to niedopuszczalne środowisko w przypadku aplikacji klasycznej. Jednak tradycyjnie żyliśmy z tym złym środowiskiem użytkownika w przypadku aplikacji internetowej, ponieważ nie wiedzieliśmy, że możemy zrobić wszystko lepiej. Myśleliśmy, że jest to ograniczenie aplikacji internetowych, gdy w rzeczywistości było to tylko ograniczenie naszej wyobraźni.

W aplikacji Ajax nie trzeba wprowadzać środowiska użytkownika do zatrzymania, aby zaktualizować stronę. Zamiast tego możesz wykonać żądanie asynchroniczne w tle, aby zaktualizować stronę. Użytkownik nie będzie musiał czekać, gdy część strony zostanie zaktualizowana.

Korzystając z technologii Ajax, możesz również zwiększyć wydajność aplikacji. Zastanów się, jak działa teraz aplikacja Contact Manager bez funkcji Ajax. Po kliknięciu grupy kontaktów cały widok indeksu musi być odtwarzany ponownie. Lista kontaktów i lista grup kontaktów musi zostać pobrana z serwera bazy danych. Wszystkie te dane muszą być przekazywane przez sieć z serwera internetowego do przeglądarki internetowej.

Po dodaniu funkcji Ajax do naszej aplikacji możemy jednak uniknąć ponownego tworzenia całej strony, gdy użytkownik kliknie grupę kontaktów. Nie musimy już pobierać grup kontaktów z bazy danych. Nie musimy również wypychać całego widoku indeksu przez przewód. Korzystając z usługi Ajax, zmniejszamy ilość pracy, jaką musi wykonać nasz serwer bazy danych i zmniejszamy ilość ruchu sieciowego wymaganego przez naszą aplikację.

Nie boj się Ajax

Niektórzy deweloperzy unikają korzystania z Ajax, ponieważ martwią się o przeglądarki downlevel. Chcą upewnić się, że ich aplikacje internetowe będą nadal działać w przypadku uzyskiwania dostępu do przeglądarki, która nie obsługuje języka JavaScript. Ponieważ Ajax zależy od języka JavaScript, niektórzy deweloperzy unikają korzystania z Ajax.

Jeśli jednak uważasz na sposób implementowania Ajax, możesz tworzyć aplikacje, które współpracują zarówno z przeglądarkami uplevel, jak i downlevel. Nasza aplikacja Contact Manager będzie działać z przeglądarkami obsługującymi język JavaScript i przeglądarki, które nie są obsługiwane.

Jeśli używasz aplikacji Contact Manager z przeglądarką, która obsługuje język JavaScript, będziesz mieć lepsze środowisko użytkownika. Na przykład po kliknięciu grupy kontaktów zostanie zaktualizowany tylko region strony wyświetlający kontakty.

Jeśli z drugiej strony używasz aplikacji Contact Manager z przeglądarką, która nie obsługuje języka JavaScript (lub ma wyłączony język JavaScript), będziesz mieć nieco mniej pożądane środowisko użytkownika. Na przykład po kliknięciu grupy kontaktów cały widok Indeks musi zostać wysłany z powrotem do przeglądarki, aby wyświetlić pasującą listę kontaktów.

Dodawanie wymaganych plików JavaScript

Musimy użyć trzech plików JavaScript w celu dodania funkcji Ajax do naszej aplikacji. Wszystkie trzy z tych plików znajdują się w folderze Scripts nowej aplikacji MVC ASP.NET.

Jeśli planujesz używać Ajax na wielu stronach w aplikacji, warto uwzględnić wymagane pliki JavaScript na stronie wzorcowej widoku aplikacji. Dzięki temu pliki JavaScript będą automatycznie uwzględniane we wszystkich stronach aplikacji.

Dodaj następujący kod JavaScript w tagu <głównym> strony wzorcowej widoku:

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

Refaktoryzacja widoku indeksu w celu korzystania z Ajax

Zacznijmy od zmodyfikowania widoku indeksu, aby kliknięcie grupy kontaktów aktualizowało tylko region widoku, w którym są wyświetlane kontakty. Czerwone pole na rysunku 1 zawiera region, który chcemy zaktualizować.

Aktualizowanie tylko kontaktów

Rysunek 01. Aktualizowanie tylko kontaktów (kliknij, aby wyświetlić obraz pełnowymiarowy)

Pierwszym krokiem jest oddzielenie części widoku, którą chcemy zaktualizować asynchronicznie do oddzielnej części (wyświetl kontrolkę użytkownika). Sekcja widoku Indeks, który wyświetla tabelę kontaktów, została przeniesiona do częściowej listy 1.

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

Zwróć uwagę, że część w liście 1 ma inny model niż widok Indeks. Atrybut Dziedziczy w <dyrektywie %@ Page %> określa, że częściowe dziedziczy z klasy ViewUserControl<Group> .

Zaktualizowany widok indeksu znajduje się na liście 2.

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

Istnieją dwie rzeczy, które należy zauważyć w zaktualizowanym widoku na liście 2. Najpierw zwróć uwagę, że cała zawartość przeniesiona do części została zastąpiona wywołaniem html.RenderPartial(). Metoda Html.RenderPartial() jest wywoływana, gdy widok indeksu jest najpierw żądany w celu wyświetlenia początkowego zestawu kontaktów.

Po drugie zwróć uwagę, że element Html.ActionLink() używany do wyświetlania grup kontaktów został zastąpiony symbolem Ajax.ActionLink(). Element Ajax.ActionLink() jest wywoływany z następującymi parametrami:

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

Pierwszy parametr reprezentuje tekst wyświetlany dla linku, drugi parametr reprezentuje wartości trasy, a trzeci parametr reprezentuje opcje Ajax. W tym przypadku użyjemy opcji UpdateTargetId Ajax, aby wskazać tag div> HTML<, który chcemy zaktualizować po zakończeniu żądania Ajax. Chcemy zaktualizować <tag div> przy użyciu nowej listy kontaktów.

Zaktualizowana metoda Index() kontrolera kontaktów znajduje się na liście 3.

Lista 3 — Controllers\ContactController.vb (metoda Indeksu)

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

Zaktualizowana akcja Index() warunkowo zwraca jedną z dwóch rzeczy. Jeśli akcja Index() jest wywoływana przez żądanie Ajax, kontroler zwraca częściowe. W przeciwnym razie akcja Index() zwraca cały widok.

Zwróć uwagę, że akcja Index() nie musi zwracać tyle danych po wywołaniu żądania Ajax. W kontekście normalnego żądania akcja Indeks zwraca listę wszystkich grup kontaktów i wybranej grupy kontaktów. W kontekście żądania Ajax akcja Index() zwraca tylko wybraną grupę. Ajax oznacza mniej pracy na serwerze bazy danych.

Nasz zmodyfikowany widok indeksu działa zarówno w przypadku przeglądarek uplevel, jak i downlevel. Jeśli klikniesz grupę kontaktów, a przeglądarka obsługuje język JavaScript, zostanie zaktualizowany tylko region widoku, który zawiera listę kontaktów. Jeśli z drugiej strony przeglądarka nie obsługuje języka JavaScript, cały widok zostanie zaktualizowany.

Nasz zaktualizowany widok indeksu ma jeden problem. Po kliknięciu grupy kontaktów wybrana grupa nie jest wyróżniona. Ponieważ lista grup jest wyświetlana poza regionem aktualizowanym podczas żądania Ajax, właściwa grupa nie zostanie wyróżniona. Rozwiążemy ten problem w następnej sekcji.

Dodawanie efektów animacji jQuery

Zwykle po kliknięciu linku na stronie internetowej można użyć paska postępu przeglądarki, aby wykryć, czy przeglądarka aktywnie pobiera zaktualizowaną zawartość. Z drugiej strony podczas wykonywania żądania Ajax pasek postępu przeglądarki nie pokazuje żadnego postępu. Może to sprawić, że użytkownicy będą zdenerwowani. Jak sprawdzić, czy przeglądarka została zamrożona?

Istnieje kilka sposobów wskazywania użytkownikowi, że praca jest wykonywana podczas wykonywania żądania Ajax. Jednym z podejść jest wyświetlenie prostej animacji. Na przykład można wynikać region, gdy żądanie Ajax rozpoczyna się i zanika w regionie po zakończeniu żądania.

Użyjemy biblioteki jQuery, która jest dołączona do platformy Microsoft ASP.NET MVC, aby utworzyć efekty animacji. Zaktualizowany widok indeksu znajduje się na liście 4.

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

Zwróć uwagę, że zaktualizowany widok indeksu zawiera trzy nowe funkcje języka JavaScript. Dwie pierwsze funkcje używają funkcji jQuery do zanikania i zanikania na liście kontaktów po kliknięciu nowej grupy kontaktów. Trzecia funkcja wyświetla komunikat o błędzie, gdy żądanie Ajax powoduje błąd (na przykład limit czasu sieci).

Pierwsza funkcja zajmuje się również wyróżnianie wybranej grupy. Klasa = wybrany atrybut jest dodawany do elementu nadrzędnego (elementu LI) klikniętego elementu. Ponownie funkcja jQuery ułatwia wybranie odpowiedniego elementu i dodanie klasy CSS.

Te skrypty są powiązane z linkami grupy za pomocą parametru Ajax.ActionLink() AjaxOptions. Zaktualizowane wywołanie metody Ajax.ActionLink() wygląda następująco:

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

Dodawanie obsługi historii przeglądarki

Zwykle po kliknięciu linku w celu zaktualizowania strony historia przeglądarki zostanie zaktualizowana. W ten sposób możesz kliknąć przycisk Wstecz przeglądarki, aby powrócić do poprzedniego stanu strony. Jeśli na przykład klikniesz grupę Kontakty znajomych, a następnie klikniesz grupę Kontakty biznesowe, możesz kliknąć przycisk Wstecz przeglądarki, aby powrócić do stanu strony po wybraniu grupy kontaktów Znajomych.

Niestety, wykonanie żądania Ajax nie powoduje automatycznej aktualizacji historii przeglądarki. Jeśli klikniesz grupę kontaktów, a lista pasujących kontaktów zostanie pobrana z żądaniem Ajax, historia przeglądarki nie zostanie zaktualizowana. Nie można użyć przycisku Wstecz przeglądarki, aby wrócić do grupy kontaktów po wybraniu nowej grupy kontaktów.

Jeśli chcesz, aby użytkownicy mogli korzystać z przycisku Wstecz przeglądarki po wykonaniu żądań Ajax, musisz wykonać nieco więcej pracy. Musisz skorzystać z funkcji zarządzania historią przeglądarki wbudowanej w ASP.NET AJAX Framework.

ASP.NET historii przeglądarki AJAX należy wykonać trzy czynności:

  1. Włącz historię przeglądarki, ustawiając właściwość enableBrowserHistory na true.
  2. Zapisz punkty historii, gdy stan widoku ulegnie zmianie, wywołując metodę addHistoryPoint().
  3. Zrekonstruuj stan widoku, gdy zostanie podniesione zdarzenie nawigacji.

Zaktualizowany widok indeksu znajduje się na liście 5.

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

Na liście 5 historia przeglądarki jest włączona w funkcji pageInit(). Funkcja pageInit() służy również do konfigurowania procedury obsługi zdarzeń dla zdarzenia nawigowania. Zdarzenie nawigowania jest wywoływane za każdym razem, gdy przycisk Prześlij dalej lub Wstecz przeglądarki powoduje zmianę stanu strony.

Metoda beginContactList() jest wywoływana po kliknięciu grupy kontaktów. Ta metoda tworzy nowy punkt historii przez wywołanie metody addHistoryPoint(). Identyfikator klikniętej grupy kontaktów jest dodawany do historii.

Identyfikator grupy jest pobierany z atrybutu expando w linku grupy kontaktów. Link jest renderowany za pomocą następującego wywołania elementu 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 })%>

Ostatni parametr przekazany do pliku Ajax.ActionLink() dodaje atrybut expando o nazwie groupid do linku (małe litery zgodności XHTML).

Gdy użytkownik osiągnie przycisk Wstecz lub Prześlij dalej przeglądarki, zostanie podniesione zdarzenie nawigacji i wywołana jest metoda navigate(). Ta metoda aktualizuje kontakty wyświetlane na stronie, aby odpowiadały stanowi strony odpowiadającej punktowi historii przeglądarki przekazanemu do metody navigate.

Wykonywanie operacji usuwania AJAX

Obecnie, aby usunąć kontakt, musisz kliknąć link Usuń, a następnie kliknąć przycisk Usuń wyświetlony na stronie potwierdzenia usuwania (zobacz Rysunek 2). Wygląda na to, że wiele żądań stron do wykonania czegoś prostego, takiego jak usuwanie rekordu bazy danych.

Strona potwierdzenia usuwania

Rysunek 02. Strona potwierdzenia usuwania (Kliknij, aby wyświetlić obraz pełnowymiarowy)

Kuszące jest pominięcie strony potwierdzenia usunięcia i usunięcie kontaktu bezpośrednio z widoku Indeks. Należy unikać tej pokusy, ponieważ zastosowanie tego podejścia powoduje otwarcie aplikacji na luki w zabezpieczeniach. Ogólnie rzecz biorąc, nie chcesz wykonywać operacji HTTP GET podczas wywoływania akcji modyfikującej stan aplikacji internetowej. Podczas usuwania chcesz wykonać operację HTTP POST lub jeszcze lepiej, operację HTTP DELETE.

Link Usuń znajduje się w częściowej listy ContactList. Zaktualizowana wersja częściowej listy ContactList znajduje się na liście 6.

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

Link Delete jest renderowany za pomocą następującego wywołania metody Ajax.ImageActionLink():

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

Uwaga

Ajax.ImageActionLink() nie jest standardową częścią platformy ASP.NET MVC. Ajax.ImageActionLink() to niestandardowe metody pomocnicze uwzględnione w projekcie Contact Manager.

Parametr AjaxOptions ma dwie właściwości. Najpierw właściwość Confirm służy do wyświetlania wyskakującego okna dialogowego potwierdzenia języka JavaScript. Po drugie, właściwość HttpMethod służy do wykonywania operacji HTTP DELETE.

Lista 7 zawiera nową akcję AjaxDelete(), która została dodana do kontrolera Kontakt.

Lista 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

Akcja AjaxDelete() jest ozdobiona atrybutem AcceptVerbs. Ten atrybut uniemożliwia wywoływanie akcji z wyjątkiem operacji HTTP innej niż operacja HTTP DELETE. W szczególności nie można wywołać tej akcji za pomocą polecenia HTTP GET.

Po usunięciu rekordu bazy danych należy wyświetlić zaktualizowaną listę kontaktów, które nie zawierają usuniętego rekordu. Metoda AjaxDelete() zwraca częściową listę Kontaktów i zaktualizowaną listę kontaktów.

Podsumowanie

W tej iteracji dodaliśmy funkcję Ajax do naszej aplikacji Contact Manager. Użyliśmy Ajax, aby poprawić czas reakcji i wydajność naszej aplikacji.

Najpierw refaktoryzowaliśmy widok Indeks, aby kliknięcie grupy kontaktów nie zaktualizowało całego widoku. Zamiast tego kliknięcie grupy kontaktów aktualizuje tylko listę kontaktów.

Następnie użyliśmy efektów animacji jQuery, aby zniknąć i zanikać na liście kontaktów. Dodanie animacji do aplikacji Ajax może służyć do udostępniania użytkownikom aplikacji odpowiednika paska postępu przeglądarki.

Dodaliśmy również obsługę historii przeglądarki do naszej aplikacji Ajax. Umożliwiliśmy użytkownikom klikanie przycisków Wstecz i Przekazywanie w przeglądarce, aby zmienić stan widoku Indeks.

Na koniec utworzyliśmy link usuwania, który obsługuje operacje HTTP DELETE. Wykonując operacje usuwania Ajax, umożliwiamy użytkownikom usuwanie rekordów bazy danych bez konieczności żądania dodatkowej strony potwierdzenia usunięcia.