• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

转:ASP.NETMVC官方教程(七)

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

Building a Contact Management ASP.NET MVC Application (C#)

Iteration #7 – Add Ajax Functionality


In this series of tutorials, we build an entire Contact Management application from start to finish. The Contact Manager application enables you to store contact information – names, phone numbers and email addresses – for a list of people.

We build the application over multiple iterations. With each iteration, we gradually improve the application. The goal of this multiple iteration approach is to enable you to understand the reason for each change.

    Iteration #1 – Create the application. In the first iteration, we create the Contact Manager in the simplest way possible. We add support for basic database operations: Create, Read, Update, and Delete (CRUD).

    Iteration #2 – Make the application look nice. In this iteration, we improve the appearance of the application by modifying the default ASP.NET MVC view master page and cascading style sheet.

    Iteration #3 – Add form validation. In the third iteration, we add basic form validation. We prevent people from submitting a form without completing required form fields. We also validate email addresses and phone numbers.

    Iteration #4 – Make the application loosely coupled. In this third iteration, we take advantage of several software design patterns to make it easier to maintain and modify the Contact Manager application. For example, we refactor our application to use the Repository pattern and the Dependency Injection pattern.

    Iteration #5 – Create unit tests. In the fifth iteration, we make our application easier to maintain and modify by adding unit tests. We mock our data model classes and build unit tests for our controllers and validation logic.

    Iteration #6 – Use test-driven development. In this sixth iteration, we add new functionality to our application by writing unit tests first and writing code against the unit tests. In this iteration, we add contact groups.

    Iteration #7 – Add Ajax functionality. In the seventh iteration, we improve the responsiveness and performance of our application by adding support for Ajax.

This Iteration

In this iteration of the Contact Manager application, we refactor our application to make use of Ajax. By taking advantage of Ajax, we make our application more responsive. We can avoid rendering an entire page when we need to update only a certain region in a page.

We’ll refactor our Index view so that we don’t need to redisplay the entire page whenever someone selects a new contact group. Instead, when someone clicks a contact group, we’ll just update the list of contacts and leave the rest of the page alone.

We’ll also change the way our delete link works. Instead of displaying a separate confirmation page, we’ll display a JavaScript confirmation dialog. If you confirm that you want to delete a contact, an HTTP DELETE operation is performed against the server to delete the contact record from the database.

Furthermore, we will take advantage of jQuery to add animation effects to our Index view. We’ll display an animation when the new list of contacts is being fetched from the server.

Finally, we’ll take advantage of the ASP.NET AJAX framework support for managing browser history. We’ll create history points whenever we perform an Ajax call to update the contact list. That way, the browser backward and forward buttons will work.

Why use Ajax?

Using Ajax has many benefits. First, adding Ajax functionality to an application results in a better user experience. In a normal web application, the entire page must be posted back to the server each and every time a user performs an action. Whenever you perform an action, the browser locks and the user must wait until the entire page is fetched and redisplayed.

This would be an unacceptable experience in the case of a desktop application. But, traditionally, we lived with this bad user experience in the case of a web application because we did not know that we could do any better. We thought it was a limitation of web applications when, in actuality, it was just a limitation of our imaginations.

In an Ajax application, you don’t need to bring the user experience to a halt just to update a page. Instead, you can perform an asynchronous request in the background to update the page. You don’t force the user to wait while part of the page gets updated.

By taking advantage of Ajax, you also can improve the performance of your application. Consider how the Contact Manager application works right now without Ajax functionality. When you click a contact group, the entire Index view must be redisplayed. The list of contacts and list of contact groups must be retrieved from the database server. All of this data must be passed across the wire from web server to web browser.

After we add Ajax functionality to our application, however, we can avoid redisplaying the entire page when a user clicks a contact group. We no longer need to grab the contact groups from the database. We also don’t need to push the entire Index view across the wire. By taking advantage of Ajax, we reduce the amount of work that our database server must perform and we reduce the amount of network traffic required by our application.

Don’t be Afraid of Ajax

Some developers avoid using Ajax because they worry about downlevel browsers. They want to make sure that their web applications will still work when accessed by a browser that does not support JavaScript. Because Ajax depends on JavaScript, some developers avoid using Ajax.

However, if you are careful about how you implement Ajax then you can build applications that work with both uplevel and downlevel browsers. Our Contact Manager application will work with browsers that support JavaScript and browsers that do not.

If you use the Contact Manager application with a browser that supports JavaScript then you will have a better user experience. For example, when you click a contact group, only the region of the page that displays contacts will be updated.

If, on the other hand, you use the Contact Manager application with a browser that does not support JavaScript (or that has JavaScript disabled) then you will have a slightly less desirable user experience. For example, when you click a contact group, the entire Index view must be posted back to the browser in order to display the matching list of contacts.

Adding the Required JavaScript Files

We’ll need to use three JavaScript files to add Ajax functionality to our application. All three of these files are included in the Scripts folder of a new ASP.NET MVC application.

If you plan to use Ajax in multiple pages in your application then it makes sense to include the required JavaScript files in your application’s view master page. That way, the JavaScript files will be included in all of the pages in your application automatically.

Add the following JavaScript includes inside the <head> tag of your view master page:

    <script src="http://www.cnblogs.com/Scripts/MicrosoftAjax.js" type="text/javascript"></script>
<script src="http://www.cnblogs.com/Scripts/MicrosoftMvcAjax.js" type="text/javascript"></script>
<script src="http://www.cnblogs.com/Scripts/jquery-1.2.6.min.js" type="text/javascript"></script>


Refactoring the Index View to use Ajax

Let’s start by modifying our Index view so that clicking a contact group only updates the region of the view that displays contacts. The red box in Figure 1 contains the region that we want to update.

Figure 01: Updating only contacts(Click to view full-size image)

The first step is to separate the part of the view that we want to update asynchronously into a separate partial (view user control). The section of the Index view that displays the table of contacts has been moved into the partial in Listing 1.

Listing 1 – Views\Contact\ContactList.ascx

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


Notice that the partial in Listing 1 has a different model than the Index view. The Inherits attribute in the <%@ Page %> directive specifies that the partial inherits from the ViewUserControl<Group> class.

The updated Index view is contained in Listing 2.

Listing 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 >
  • Enable Browser History by setting the enableBrowserHistory property to true.
  • Save history points when the state of a view changes by calling the addHistoryPoint() method.
  • Reconstruct the state of the view when the navigate event is raised.
  • The updated Index view is contained in Listing 5.

    Listing 5 – Views\Contact\Index.aspx

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

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


    <script type="text/javascript">

    var _currentGroupId = -1;

    Sys.Application.add_init(pageInit);

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

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

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

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

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

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

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

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

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

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

    </script>


    <ul >Click to view full-size image)

    It is tempting to skip the delete confirmation page and delete a contact directly from the Index view. You should avoid this temptation because taking this approach opens your application to security holes. In general, you don’t want to perform an HTTP GET operation when invoking an action that modifies the state of your web application. When performing a delete, you want to perform an HTTP POST, or better yet, an HTTP DELETE operation.

    The Delete link is contained in the ContactList partial. An updated version of the ContactList partial is contained in Listing 6.

    Listing 6 – Views\Contact\ContactList.ascx

    <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ContactManager.Models.Group>" %>
    <%@ Import Namespace="Helpers" %>
    <table class="data-table" cellpadding="0" cellspacing="0">
    <thead>
    <tr>
    <th class="actions edit">
    Edit
    </th>
    <th class="actions delete">
    Delete
    </th>
    <th>
    Name
    </th>
    <th>
    Phone
    </th>
    <th>
    Email
    </th>
    </tr>
    </thead>
    <tbody>
    <% foreach (var item in Model.Contacts)
    { %>
    <tr>
    <td class="actions edit">
    <a href='<%= Url.Action("Edit", new {id=item.Id}) %>'><img src="https://www.cnblogs.com/Content/Edit.png" alt="Edit" /></a>
    </td>
    <td class="actions delete">
    <%= Ajax.ImageActionLink("http://www.cnblogs.com/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>


    The Delete link is rendered with the following call to the Ajax.ImageActionLink() method:

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

    The Ajax.ImageActionLink() is not a standard part of the ASP.NET MVC framework. The Ajax.ImageActionLink() is a custom helper methods included in the Contact Manager project.

    The AjaxOptions parameter has two properties. First, the Confirm property is used to display a popup JavaScript confirmation dialog. Second, the HttpMethod property is used to perform an HTTP DELETE operation.

    Listing 7 contains a new AjaxDelete() action that has been added to the Contact controller.

    Listing 7 – Controllers\ContactController.cs (AjaxDelete)

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

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

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

    The AjaxDelete() action is decorated with an AcceptVerbs attribute. This attribute prevents the action from being invoked except by any HTTP operation other than an HTTP DELETE operation. In particular, you cannot invoke this action with an HTTP GET.

    After you delete database record, you need to display the updated list of contacts that does not contain the deleted record. The AjaxDelete() method returns the ContactList partial and the updated list of contacts.

    Summary

    In this iteration, we added Ajax functionality to our Contact Manager application. We used Ajax to improve the responsiveness and performance of our application.

    First, we refactored the Index view so that clicking a contact group does not update the entire view. Instead, clicking a contact group only updates the list of contacts.

    Next, we used jQuery animation effects to fade out and fade in the list of contacts. Adding animation to an Ajax application can be used to provide users of the application with the equivalent of a browser progress bar.

    We also added browser history support to our Ajax application. We enabled users to click the browser Back and Forward buttons to change the state of the Index view.

    Finally, we created a delete link that supports HTTP DELETE operations. By performing Ajax deletes, we enable users to delete database records without requiring the user to request an additional delete confirmation page.

    鲜花

    握手

    雷人

    路过

    鸡蛋
    该文章已有0人参与评论

    请发表评论

    全部评论

    专题导读
    热门推荐
    热门话题
    阅读排行榜

    扫描微信二维码

    查看手机版网站

    随时了解更新最新资讯

    139-2527-9053

    在线客服(服务时间 9:00~18:00)

    在线QQ客服
    地址:深圳市南山区西丽大学城创智工业园
    电邮:jeky_zhao#qq.com
    移动电话:139-2527-9053

    Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap