实现Ajax增强用户体验ASP.NET MVC 3
[翻译]ASP.NET MVC 3 开发的20个秘诀(十三)[20 Recipes for Programming MVC 3]:实现Ajax增强用户体验
议题
单击链接的时候,由于网页刷新内容需要重新加载,会感觉整个过程变的非常缓慢,尤其在我们只需要更新少量内容的时候感觉更加明显。
解决方案
修改之前的示例,将 Html.ActionLink 创建的链接更改为由 Ajax 辅助类 Ajax.ActionLink 创建,使链接点击时只加载需要改变的内容。
讨论
MVC 框架提供了几个非常棒的辅助类。在目前为止本书使用最后的就是 Html Helper 类,几乎之前所有的视图类都至少使用过一次。在这个秘诀中,将使用 AjaxHelper 辅助类替换 Books 和 Index 视图中所有的 HtmlHelper 辅助类。
要想实现 Ajax 视需要一点额外的设置才能使用的。通常情况下,也正是这点儿额外的工作阻止了开发人员使用它。但是我认为花费额外的时间去实现它是值得的,因为这将使用户在使用时获得非常好的体验。
在程序的配置文件 Web.config 文件中,设置 ClientValidationEnabled 和UnobtrusiveJavaScriptEnabled值为 True :
<? xml version="1.0" ?>
< configuration >
< connectionStrings >
< add name ="ApplicationServices" connectionString =
"data source=.\SQLEXPRESS;Integrated Security=SSPI;
AttachDBFilename=|DataDirectory|aspnetdb.mdf;
User Instance=true" providerName ="System.Data.SqlClient" />
</ connectionStrings >
< appSettings >
< add key ="webpages:Version" value ="1.0.0.0" />
< add key ="ClientValidationEnabled" value ="true" />
< add key ="UnobtrusiveJavaScriptEnabled" value ="true" />
< add key ="smtpServer" value ="localhost" />
< add key ="smtpPort" value ="25" />
< add key ="smtpUser" value ="" />
< add key ="smtpPass" value ="" />
</ appSettings >
< system .web >
< compilation debug ="true" targetFramework ="4.0" >
< assemblies >
< add assembly ="System.Web.Abstractions,
Version=4.0.0.0, Culture=neutral,
PublicKeyToken=31BF3856AD364E35" />
< add assembly ="System.Web.Helpers,
Version=1.0.0.0, Culture=neutral,
PublicKeyToken=31BF3856AD364E35" />
< add assembly ="System.Web.Routing,
Version=4.0.0.0, Culture=neutral,
PublicKeyToken=31BF3856AD364E35" />
< add assembly ="System.Web.Mvc,
Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31BF3856AD364E35" />
< add assembly ="System.Web.WebPages,
Version=1.0.0.0, Culture=neutral,
PublicKeyToken=31BF3856AD364E35" />
< add assembly ="System.Data.Entity,
Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089" />
</ assemblies >
</ compilation >
...
</ system.web >
...
</ configuration >
完成最后的配置步骤,需要包含几个 Javascript 文件。这些文件需要在各个视图中共享使用,在 Views/Shared/_Layout.cshtml 文件中,将这两个 Javascript 文件包含到 <head> 标记中:
<! DOCTYPE html >
< html >
< 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 >
< body >
< div class ="page" >
< div id ="header" >
< div id ="title" >
< h1 > My MVC Application </ h1 >
</ div >
< div id ="logindisplay" >
@Html.Partial("_LogOnPartial")
[ @Html.ActionLink("English", "ChangeLanguage",
"Home", new { language = "en" }, null) ]
[ @Html.ActionLink("Fran?ais", "ChangeLanguage",
"Home", new { language = "fr" }, null) ]
</ div >
< div id ="menucontainer" >
< ul id ="menu" >
< li >
@Html.ActionLink("Home", "Index", "Home")
</ li >
< li >
@Html.ActionLink("About", "About", "Home")
</ li >
</ ul >
</ div >
</ div >
< div id ="main" >
@RenderBody()
</ div >
< div id ="footer" >
</ div >
</ div >
</ body >
</ html >
将这些文件自动嵌入到 MVC3 应用程序中,也就完成了 Ajax 核心功能的配置。接下来,我们需要修改 Books/Index 视图。在下面的示例中,修改了三个过滤器链接和列首的排序链接,用 Ajax.ActionLink 替换 Html.ActionLink :
@model PagedList.IPagedList < MvcApplication4 .Models.Book >
@if (IsAjax)
{
Layout = null;
}
< h2 > @MvcApplication4.Resources.Resource1.BookIndexTitle </ 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
}
|
@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
}
|
@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 链接时, Ajax 请求会更新 ID 为“ main ”的 HTML 标签。如果仔细看了之前更改的共享布局的页面,会发现它包含一个 ID 为 "main" 的标记。事实上,这个是 @RenderBody() 方法在视图中输出的内容的容器。
同时我们在视图的顶部做了一个非常重要的检测,如果 Ajax 请求完成,则将 Layout 属性设置为空。这是一个非常重要的设置,因为 Ajax 请求并不是只是包含视图的内容,而是会包含整个布局的内容,这样就会将整个布局再次放入到当前布局中。
为了完成这个示例,需要将 Shared/Pageing 视图修改为使用 AjaxHelper 类实现:
< p >
@if (Model.HasPreviousPage)
{
@Ajax.ActionLink(" < < First ", "Index", new {
page = 1,
sortOrder = ViewBag.CurrentSortOrder,
filter = ViewBag.CurrentFilter,
Keyword = ViewBag.CurrentKeyword },
new AjaxOptions { UpdateTargetId = "main" })
@Html.Raw(" ");
@Ajax.ActionLink("< Prev", "Index", new {
page = Model.PageNumber - 1,
sortOrder = ViewBag.CurrentSortOrder,
filter = ViewBag.CurrentFilter,
Keyword = ViewBag.CurrentKeyword },
new AjaxOptions { UpdateTargetId = "main" })
}
else
{
@:<< First
@Html.Raw(" ");
@:< Prev
}
@if (Model.HasNextPage)
{
@Ajax.ActionLink("Next > ", "Index", new {
page = Model.PageNumber + 1,
sortOrder = ViewBag.CurrentSortOrder,
filter = ViewBag.CurrentFilter,
Keyword = ViewBag.CurrentKeyword },
new AjaxOptions { UpdateTargetId = "main" })
@Html.Raw(" ");
@Ajax.ActionLink("Last >>", "Index", new {
page = Model.PageCount,
sortOrder = ViewBag.CurrentSortOrder,
filter = ViewBag.CurrentFilter,
Keyword = ViewBag.CurrentKeyword },
new AjaxOptions { UpdateTargetId = "main" })
}
else
{
@:Next >
@Html.Raw(" ")
@:Last >>
}
</ p >
现在,当用户点击更改书籍列表的链接,更新书籍列表整个页面将不会重新载入,这样为用户提供了更快、更好的用户体验。
此外,如果客户端不支持 Javascript (例如,当搜索引擎检索访问时),链接依然可以正常工作,即使是用户禁止了 Javascript 或者搜索引擎仍然可以通过链接访问当一个正常的完整的页面重载的内容。
参考
AjaxHelper 原书地址 书籍源代码
ASP.NET MVC
[翻译]ASP.NET MVC 3 开发的20个秘诀(十三)[20 Recipes for Programming MVC 3]:实现Ajax增强用户体验
posted @ 2011-12-18 16:57 O2DS 阅读(335) | 评论 (0) 编辑
[翻译]ASP.NET MVC 3 开发的20个秘诀(十二)[20 Recipes for Programming MVC 3]:缩放图片尺寸创建缩略图
posted @ 2011-12-17 10:17 O2DS 阅读(835) | 评论 (2) 编辑
[翻译]ASP.NET MVC 3 开发的20个秘诀(十一)[20 Recipes for Programming MVC 3]:通过表单上传文件
posted @ 2011-12-15 23:17 O2DS 阅读(951) | 评论 (2) 编辑
[翻译]ASP.NET MVC 3 开发的20个秘诀(十)[20 Recipes for Programming MVC 3]:通过关键字进行列表搜索
posted @ 2011-12-15 10:32 O2DS 阅读(961) | 评论 (3) 编辑
[翻译]ASP.NET MVC 3 开发的20个秘诀(九)[20 Recipes for Programming MVC 3]:对列表进行筛选
posted @ 2011-12-14 12:33 O2DS 阅读(1011) | 评论 (0) 编辑
[翻译]ASP.NET MVC 3 开发的20个秘诀(八)[20 Recipes for Programming MVC 3]:对列表进行分页
posted @ 2011-12-13 16:15 O2DS 阅读(757) | 评论 (2) 编辑
[翻译]ASP.NET MVC 3 开发的20个秘诀(七)[20 Recipes for Programming MVC 3]:对列表进行排序
posted @ 2011-12-12 13:50 O2DS 阅读(1152) | 评论 (0) 编辑
[翻译]ASP.NET MVC 3 开发的20个秘诀(六)[20 Recipes for Programming MVC 3]:找回忘记的密码
posted @ 2011-12-10 20:00 O2DS 阅读(835) | 评论 (0) 编辑
[翻译]ASP.NET MVC 3 开发的20个秘诀(五)[20 Recipes for Programming MVC 3]:发送欢迎邮件
posted @ 2011-12-09 09:32 O2DS 阅读(1304) | 评论 (9) 编辑
[翻译]ASP.NET MVC 3 开发的20个秘诀(四)[20 Recipes for Programming MVC 3]:实现多语言支持
posted @ 2011-12-07 11:19 O2DS 阅读(923) | 评论 (2) 编辑
[翻译]ASP.NET MVC 3 开发的20个秘诀(三)[20 Recipes for Programming MVC 3]:验证用户输入
posted @ 2011-12-06 22:16 O2DS 阅读(1198) | 评论 (0) 编辑
[翻译]ASP.NET MVC 3 开发的20个秘诀(二)[20 Recipes for Programming MVC 3]:自动生成控制器和视图
posted @ 2011-12-03 23:31 O2DS 阅读(1122) | 评论 (2) 编辑
[翻译]ASP.NET MVC 3 开发的20个秘诀(一)[20 Recipes for Programming MVC 3]:通过密码验证限制访问视图
posted @ 2011-11-29 12:04 O2DS 阅读(1880) | 评论 (7) 编辑
作者: Leo_wl
出处: http://www.cnblogs.com/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息查看更多关于实现Ajax增强用户体验ASP.NET MVC 3的详细内容...