[转载]ASP.NET MVC3 20个秘方-(13)使用Ajax Helper 提高用户体验

[转载]【译】MVC3 20个秘方-(13)使用Ajax Helper 提高用户体验 – 技术弟弟 – 博客园.

问题

当你点击链接时,整个的网页都被重新加载。尤其是你仅仅一小点内容需要被更新时,这将被感觉是一个很慢的过程。

解决方案

更新之前创建的HTML.ActionLink 去调用ajax 帮助类。Ajax.ActionLink 仅仅去重新加载那些发生变化的内容。

讨论

MVC提供了几个给力的帮助类。到目前为止,这本书中已经广泛的应用了HTML Helper。在过去创建的所有view中,HTML helper至少都使用过一次。在这个秘方中,我们将使用AjaxHelper类替换掉Book/Index中的HtmlHelper 类。

实现Ajax需要一点额外的设置才可以使用。通常情况下我发现这个额外的工作,可以打消开发人员使用它的念头。我要让大家知道,额外的安装设置是值得的,因为带来的好处是获得了更好的用户体验,这是非常值得努力去做的。

步骤从web.config开始。2个关键的地方要被设置成true. ClientValidationEnabled 和UnobtrusiveJavaScriptEnabled。

译者:原书中代码引入了整个web.config文件。我们只需要到appSettings节点下即可找到这两个keys。

  <appSettings>
    <add key="webpages:Version" value="1.0.0.0" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
  </appSettings>

接下来的步骤是我们要引入几个JavaScript 文件。我们要在里shared 的layout文件夹里完成这件事,因为几乎我们创建所有的view时都会引用它(布局模板)。在Views/Shared /_Layout.cshtml 文件的<head>标签中。我们引入2个javascript 文件,代码如下:

<head>
    <title>@ViewBag.Title</title>
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")"type="text/javascript"></script>
</head>

这些文件被自动的包含在基础MVC3应用程序中。(译者:你可以从scripts文件夹中找到他们)。以上的步骤完成AJAX的核心配置。接下来, 我们要更新Book/index view。在下边的例子里,三个filter link和sortable header link将用Ajax.ActionLink 替换Html.ActionLink.代码如下:

@model PagedList.IPagedList<MvcApplication.Models.Book>
@if (IsAjax)
{
    Layout = null;
}
<h2>
    Title</h2>
<p>
    @Html.ActionLink("Create New", "Create")
</p>
<p>
    Show:
    @if (ViewBag.CurrentFilter != "")
    {
        @Ajax.ActionLink("All", "Index",
                            new
                            {
                                sortOrder = ViewBag.CurrentSortOrder,
                                Keyword = ViewBag.CurrentKeyword
                            },
                            new AjaxOptions { UpdateTargetId = "main" })
    }
    else
    {
        @:All
        }
    &nbsp; | &nbsp;
    @if (ViewBag.CurrentFilter != "NewReleases")
    {
        @Ajax.ActionLink("New Releases", "Index", new
                        {
                            filter = "NewReleases",
                            sortOrder = ViewBag.CurrentSortOrder,
                            Keyword = ViewBag.CurrentKeyword
                        },
                        new AjaxOptions { UpdateTargetId = "main" })
    }
    else
    {
        @:New Releases
        }
    &nbsp; | &nbsp;
    @if (ViewBag.CurrentFilter != "ComingSoon")
    {
        @Ajax.ActionLink("Coming Soon", "Index", new
                        {
                            filter = "ComingSoon",
                            sortOrder = ViewBag.CurrentSortOrder,
                            Keyword = ViewBag.CurrentKeyword
                        },
                        new AjaxOptions { UpdateTargetId = "main" })
    }
    else
    {
        @:Coming Soon
        }
</p>
@using (Html.BeginForm())
{
    @:Search: @Html.TextBox("Keyword")<input type="submit" value="Search" />

}
@Html.Partial("_Paging")
<table>
    <tr>
        <th>
            @Ajax.ActionLink("Title", "Index", new
                            {
                                sortOrder = ViewBag.TitleSortParam,
                                filter = ViewBag.CurrentFilter,
                                Keyword = ViewBag.CurrentKeyword
                            },
                            new AjaxOptions { UpdateTargetId = "main" })
        </th>
        <th>
            @Ajax.ActionLink("Isbn", "Index", new
                            {
                                sortOrder = ViewBag.IsbnSortParam,
                                filter = ViewBag.CurrentFilter,
                                Keyword = ViewBag.CurrentKeyword
                            },
                            new AjaxOptions { UpdateTargetId = "main" })
        </th>
        <th>
            Summary
        </th>
        <th>
            @Ajax.ActionLink("Author", "Index", new
                            {
                                sortOrder = ViewBag.AuthorSortParam,
                                filter = ViewBag.CurrentFilter,
                                Keyword = ViewBag.CurrentKeyword
                            },
                            new AjaxOptions { UpdateTargetId = "main" })
        </th>
        <th>
            Thumbnail
        </th>
        <th>
            @Ajax.ActionLink("Price", "Index", new
                            {
                                sortOrder = ViewBag.PriceSortParam,
                                filter = ViewBag.CurrentFilter,
                                Keyword = ViewBag.CurrentKeyword
                            },
                            new AjaxOptions { UpdateTargetId = "main" })
        </th>
        <th>
            @Ajax.ActionLink("Published", "Index", new
                            {
                                sortOrder = ViewBag.PublishedSortParam,
                                filter = ViewBag.CurrentFilter,
                                Keyword = ViewBag.CurrentKeyword
                            },
                            new AjaxOptions { UpdateTargetId = "main" })
        </th>
        <th>
        </th>
    </tr>
    @foreach (var item in Model)
    {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Title)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Isbn)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Summary)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Author)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Thumbnail)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Price)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Published)
            </td>
            <td>
                @Html.ActionLink("Edit","Edit", new { id = item.ID }) |
                @Html.ActionLink("Details","Details", new { id = item.ID }) |
                @Html.ActionLink("Delete","Delete", new { id = item.ID })
            </td>
        </tr>
    }
</table>
@Html.Partial("_Paging")

译者:上边代码标绿的地方就是我们更新的地方。

我们做的关键的事就是在ActionLink的最后一个参数添加了AjaxOptions。 这意味着一旦用户点击了这个AJAX link,AJAX请求的结果将会更新id 是“main”的html元素。如果你看看share文件夹中早期我们修改的layout文件,你会注意到有一个<div>的id 是“main”。实际上,这个div就是@Renderbody()的容器,它是一个view输出的地方。

另外一个重要的事就是我们在view的顶端加了一个AJAX是否完成的检测。如果请求通过AJAX完成,layout设 置成null。这是一个非常重要的因素,因为如果它没完成,Ajax请求的结果将会包含不仅仅是view的result,也会包含整个layout,而没 必要再去替换掉layout了。

为了完成这个示例,share文件夹下的_Paging也要使用Ajax helper更新,代码如下:

<p>
    @if (Model.HasPreviousPage)
    {
        @Ajax.ActionLink("<< First", "Index", new
                        {
                            page = 1,
                            sortOrder = ViewBag.CurrentSortOrder,
                            filter = ViewBag.CurrentFilter
                        },
                        new AjaxOptions { UpdateTargetId ="main" })
        @Html.Raw("&nbsp;");
        @Html.ActionLink("< Prev", "Index", new
                        {
                            page = Model.PageNumber - 1,
                            sortOrder = ViewBag.CurrentSortOrder,
                            filter = ViewBag.CurrentFilter
                        },  new AjaxOptions { UpdateTargetId ="main" })
    }
    else
    {
        @:<< First
        @Html.Raw("&nbsp;");
        @:< Prev
    }
    &nbsp;&nbsp;
    @if (Model.HasNextPage)
    {
        @Ajax.ActionLink("Next >", "Index", new
                        {
                            page = Model.PageNumber + 1,
                            sortOrder = ViewBag.CurrentSortOrder,
                            filter = ViewBag.CurrentFilter
                        },  new AjaxOptions { UpdateTargetId ="main" })
        @Html.Raw("&nbsp;");
        @Ajax.ActionLink("Last >>", "Index", new
                        {
                            page = Model.PageCount,
                            sortOrder = ViewBag.CurrentSortOrder,
                            filter = ViewBag.CurrentFilter
                        },  new AjaxOptions { UpdateTargetId ="main" })
    }
    else
    {
        @:Next >
        @Html.Raw("&nbsp;")
        @:Last >>
    }
</p>

现在,当用户点击一个link 改变book 列表时,整个的页面不会被重新载入并且仅仅是图书列表被更新。这提供了一个更好、更快的用户体验。

而且,如果客户端不支持javascript(例如,一个搜索引擎访问),这个link将像以前一样工作。它将重新载入整个页面。

另请参见

AjaxHelper

赞(0) 打赏
分享到: 更多 (0)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏