标签:
一、Ajax的前世今生
我一直觉得google是一家牛逼的公司,为什么这样说呢?《舌尖上的中国》大家都看了,那些美食估计你是百看不厌,但是里边我觉得其实也有这样的一个哲学:关于食材,对于种食材的菜农来讲,可能它的价值就是卖到市场上而已;而对于大厨们来讲,却可以像变魔术一样将不起眼的食材变成美味佳肴。大厨们不拥有食材,但他们却可以恰到好处的搭配使用它们,这就是他们的精明之处。而google同样是IT界的大厨:java诞生了这么多年,却没有被充分利用,而google却用它搞出来了震惊世界的Android; HTML、XML、Javascript这些个东东都不是google发明的吧,但却是google却用它们发明了Ajax, google earth、google suggest以及gmail等ajax技术的广泛应用,向这个世界带来了ajax技术,从此ajax与web再也不能分离。这里也向我们程序猿提了个醒:如果不能把所学的各种技术转化为money或者生产力,那么一切都是扯淡!
精确的说,ajax并不能提高从服务器端下载数据的速度,而只是使这个等待不那么令人沮丧,这就是所谓的用户体验了,但就这一点就足以产生巨大的影响和震动,因为它已经革了c/s东东的命,它无疑是WEB时代的宠儿~
Ajax的给我们带来的好处大家基本上都深有体会,略表一二:
1、最大的一点是页面无刷新,在页面内与服务器通信,给用户的体验非常好。
2、使用异步方式与服务器通信,不需要打断用户的操作,具有更加迅速的响应能力。
3、可以把以前一些服务器负担的工作转嫁到客户端,利用客户端闲置的能力来处理,减轻服务器和带宽的负担,节约空间和宽带租用成本。并且减轻服务器的负担,ajax的原则是“按需取数据”,可以最大程度的减少冗余请求,和响应对服务器造成的负担。
4、基于标准化的并被广泛支持的技术,不需要下载插件或者小程序。
缺点也有,但是瑕不掩瑜,所以还是要用!ASP.NET MVC作为微软的当家利器自然也要拥抱Ajax了,这里就说说他们之间那些事儿!
二、ASP.NET MVC之Ajax
这里不会用原生的Ajax的,其实我连说都不想说,土的掉渣,更别提那个微软自己的那个已经玩完的Ajax框架了,所以下面的Ajax都不是原生的。
MVC框架本身提供了AjaxHelper类用于Ajax异步请求,所以如果你想省事,就用这种方式吧~
AjaxHelper帮助器方法:
Helper method |
Description |
Ajax.ActionLink |
Creates a hyperlink to a controller action that fires an Ajax request when clicked |
Ajax.RouteLink |
Similar to Ajax.ActionLink, but generates a link to a particular route instead of a named controller action |
Ajax.BeginForm |
Creates a form element that submits its data to a particular controller action using Ajax |
Ajax.BeginRouteForm | Similar to Ajax.BeginForm, but creates a form that sub- mits its data to a particular route instead of a named control- ler action |
Ajax.GlobalizationScript | Creates an HTML script element that references a script that contains culture information |
Ajax.JavaScriptStringEncode | Encodes a string to make sure that it can safely be used inside JavaScript |
上面的方法貌似很多,但是实际开发中用到的就两个帮助器方法而已:
Ajax.ActionLink()和Ajax.BeginForm()
这里有个问题:怎样让项目知道我们用的是MVC自带的Ajax呢?
SO EASY:
A、在Web.config里边配置:
1.
<add key=
"UnobtrusiveJavaScriptEnabled"
value=
"true"
/>
B、在页面中引用下面的js类库即可:
1.
@section
scripts{
2.
<script type=
"text/javascript"
src=
" @Url.Content("
~/Scripts/jquery.unobtrusive-ajax.js
")"
></script>
3.
}
一般更为常见的是在布局页/Views/Shared/_Layout.cshtml 中引入,例如:
01.
<!DOCTYPE html>
02.
<html>
03.
<head>
04.
<meta charset=
"utf-8"
/>
05.
<meta name=
"viewport"
content=
"width=device-width"
/>
06.
<title>@ViewBag.Title</title>
07.
<script src=
"~/Scripts/jquery-1.8.2.min.js"
></script>
08.
<script src=
"~/Scripts/jquery.unobtrusive-ajax.min.js"
></script>
09.
</head>
10.
<body>
11.
@RenderBody()
12.
</body>
13.
</html>
Ajax.ActionLink():
向客户端输出一个链接地址,当单击这个链接时可以Ajax调用Controller中的方法,Ajax.ActionLink()方法有许多重载,下面是其重载之一:
public static string ActionLink(this AjaxHelper ajaxHelper, string linkText, string actionName, object routeValues, AjaxOptions ajaxOptions);
linkText:是显示在客户端的文本
actionName:是Action的名字,默认情况下我们会使用当前的Controller。
routeValues:将传入到Controller中方法的参数
ajaxOptions:配置Ajax的一些选项
Confirm |
获取或设置提交请求之前,显示在确认窗口中的消息。 |
HttpMethod |
获取或设置 HTTP 请求方法(“Get”或“Post”)。 |
InsertionMode |
获取或设置指定如何将响应插入目标 DOM 元素的模式。 |
LoadingElementId |
获取或设置加载 Ajax 函数时要显示的 HTML 元素的 id 特性。 |
OnBegin |
获取或设置更新页面之前,恰好调用的 JavaScript 函数的名称。 |
OnComplete |
获取或设置实例化响应数据之后但更新页面之前,要调用的 JavaScript 函数。 |
OnFailure |
获取或设置页面更新失败时,要调用的 JavaScript 函数。 |
OnSuccess |
获取或设置成功更新页面之后,要调用的 JavaScript 函数。 |
UpdateTargetId |
获取或设置要使用服务器响应来更新的 DOM 元素的 ID。 |
Url |
获取或设置要向其发送请求的 URL。 |
备注:
OnComplete和OnSuccess的区别:OnComplete是获取了Http请求时引发的,此时页面还没有进行更新,OnSuccess是在页面已经更新后引发的。 当加载数据须要花较长时候,为了避免假死状况,该当给用户一个反馈信息,如“正在加载...”字样。在 MVC 的 Unobtrusive Ajax 中经用AjaxOptions选项的 LoadingElementId 和 LoadingElementDuration 两个属性可轻松做到这一点,例如下面的设置:1.
AjaxOptions ajaxOpts =
new
AjaxOptions {
2.
UpdateTargetId =
"tableBody"
,
3.
Url = Url.Action(
"GetPeopleData"
),
4.
LoadingElementId =
"loading"
,
5.
LoadingElementDuration =
1000
,
6.
};
1.
AjaxOptions ajaxOpts =
new
AjaxOptions {
2.
UpdateTargetId =
"tableBody"
,
3.
Url = Url.Action(
"GetPeopleData"
)
4.
};
然后查看它生成的 form 属性:
1.
<form id=
"form0"
action=
"/People/GetPeople"
method=
"post"
data-ajax-url=
"/People/GetPeopleData"
data-ajax-=
"#tableBody"
<br>data-ajax-mode=
"replace"
data-ajax=
"true"
>
它生成了两个 Url,分别为 action 属性 和 data-ajax-url 属性的值,前者是 Ajax.BeginForm() 办法按照当前 controller 和 action 名称生成的,后者是 AjaxOptions 的 Url 属性生成的。当浏览器没有禁用 JavaScript 时,Unobtrusive Ajax JS库会获取 data-ajax-url 属性的值作为 Url 产生 ajax 恳求。当浏览器禁用了 JavaScript 时,天然 action 属性的值决定了默示提交的 Url,自然访问该页面。固然局部未能刷新,但不会让用户体验很差。
使用Html.ActionLink方法的一个栗子:
1.
@Ajax
.ActionLink(
"点击我"
,
"getEntry"
,
new
{ id = item.Id },
new
AjaxOptions <br>{ HttpMethod =
"Post"
, UpdateTargetId =
"detailsID"
, InsertionMode = InsertionMode.Replace })
说明:“点击我”是生产的超链接文字;“getEntry”是当前控制器的Action方法;id = item.Id是向Action方法传递的参数;HttpMethod = "Post", 说明Ajax请求是post方式的;UpdateTargetId = "detailsID"说明了要更新的html块的Id标记元素;InsertionMode = InsertionMode.Replace说明是替换ID为detailsID的元素里边的内容。
实际应用:
(1)使用Ajax.ActionLink请求返回值为 Json格式的Controller方法
在Index.cshtml中使用ActionLink,如下:
1.
@Ajax
.ActionLink(
"点击我"
,
"JsonDetails"
,
new
{ id = item.Id }, <br>
new
AjaxOptions { HttpMethod =
"Post"
, InsertionMode = InsertionMode.Replace, OnSuccess =
"Show"
})
相应的Controller:
1.
public
ActionResult JsonDetails(
int
id =
0
)
2.
{
3.
GuestbookEntry entry = _db.Entries.First(c => c.Id == id);
4.
return
Json(entry, JsonRequestBehavior.AllowGet);
5.
}
同时需要在Index.cshtml中添加请求成功的相应js函数Show,以便更新ID属性为detailsID的DIV内容:
1.
<script type=
"text/javascript"
>
2.
function Show(data) {
3.
$(
"#detailsID"
).html(
"姓名:"
+ data.Name +
" 消息:"
+ data.Message);
4.
}
5.
</script>
(2)使用Ajax.ActionLink 请求返回值为PartialView格式的Controller方法
在Index.cshtml中
1.
@Ajax
.ActionLink(
"AjaxPartialView"
,
"Details"
,
new
{ id = item.Id }, <br>
new
AjaxOptions { HttpMethod =
"Get"
, UpdateTargetId =
"detailsID"
})
相应的Controller:
01.
public
ActionResult Details(
int
id =
0
)
02.
{
03.
GuestbookEntry entry = _db.Entries.First(c => c.Id == id);
04.
if
(Request.IsAjaxRequest())
05.
{
06.
return
PartialView(entry);
07.
}
08.
return
View(entry);
09.
}
在这里我们使用Request.IsAjaxRequest()来判断是否为Ajax请求,如果是则返回PartialView,否则返回View。最后,返回的内容会直接更新到ID属性为detailsID的DIV中。
Ajax.BeginForm
这个方法用于异步提交表单,比如一个新增信息的页面Create.cshtml,下面的代码会使表单以Ajax方式提交
01.
@model
MvcApplication5.Models.GuestbookEntry
02.
<script type=
"text/javascript"
src=
" @Url.Content("
~/Scripts/jquery.unobtrusive-ajax.js
")"
></script>
03.
<script type=
"text/javascript"
>
04.
function success(data) {
05.
alert(data);
06.
}
07.
</script>
08.
@{
09.
ViewBag.Title =
"Create"
;
10.
}
11.
12.
<h4>Create</h4>
13.
14.
@using
(Ajax.BeginForm(
new
AjaxOptions {
15.
HttpMethod=
"Post"
,
16.
OnSuccess =
"success"
17.
}))
18.
{
19.
@Html
.ValidationSummary(
true
)
20.
21.
<fieldset>
22.
<legend>GuestbookEntry</legend>
23.
<div
class
=
"editor-label"
>
24.
@Html
.LabelFor(model => model.Name)
25.
</div>
26.
<div
class
=
"editor-field"
>
27.
@Html
.EditorFor(model => model.Name)
28.
@Html
.ValidationMessageFor(model => model.Name)
29.
</div>
30.
<div
class
=
"editor-label"
>
31.
@Html
.LabelFor(model => model.Message)
32.
</div>
33.
<div
class
=
"editor-field"
>
34.
@Html
.EditorFor(model => model.Message)
35.
@Html
.ValidationMessageFor(model => model.Message)
36.
</div>
37.
<p>
38.
<input type=
"submit"
value=
"Create"
/>
39.
</p>
40.
</fieldset>
41.
}
控制器的代码如下:
01.
[HttpPost]
02.
public
ActionResult Create(GuestbookEntry entry)
03.
{
04.
if
(ModelState.IsValid)
05.
{
06.
entry.DateAdded = DateTime.Now;
07.
_db.Entries.Add(entry);
08.
_db.SaveChanges();
09.
return
Content(
"New Entry successfully added."
);
10.
}
11.
else
{
12.
return
View();
13.
}
14.
}
注:
貌似上面的Ajax方法很方便,但是它的工作原理可能大家不是很清楚,这里就大概说一下吧~
当调用 Ajax.BeginForm 方法后,经由选项 AjaxOptions 对象设置的属性将会被转化成 form 表单的属性,这些属性以 data-ajax 开首,如本示例生成的 form 表单:
1.
<form action=
"/GuestBook/Create"
data-ajax=
"true"
data-ajax-mode=
"replace"
data-ajax-=
"#tableBody"
id=
"form0"
method=
"post"
>
当 Create.cshtml 视图加载完成并浮现 Html 页面时,jquery.unobtrusive-ajax.js 库会寻找所有 data-ajax == true的元素,然后按照其它以 data-ajax 开头的属性值,jQuery 库中的函数将知道如何去执行 Ajax 请求。
(1)使用JQuery的Ajax请求返回值为 Json格式的Controller方法
原理就是用JQuery的Ajax方法请求Action方法,返回值设为JSON,然后对JSON数据进行处理,例如用js函数进行处理
举个栗子:
01.
<script type=
"text/javascript"
language=
"javascript"
>
02.
$(function(){
03.
GetRoomInfoList();<br> });
04.
function GetRoomInfoList() {
05.
showDivLoading();
//异步加载数据时的浮层
06.
$.ajax({
07.
type:
"Post"
,
08.
url:
"@Url.Content("
~/Room/GetRoomInfoShipId
")"
,
//异步请求的URL,就是Room控制器方法GetRoomInfoShipId(long shipId)
09.
dataType:
"json"
,
//要求返回数据为JSON格式
10.
data:{shipId:$(
"#ShipIdForSearch"
).val()},
//异步请求的参数
11.
success: function(data){
12.
$(
"#RoomInfoListTable"
).empty();
//清空里面的所有内容
13.
$.each(data, function(i, item){
//用js拼字符串处理数据,这里是显示所有房型列表信息
14.
15.
var str=
"<tr>"
;
16.
str+=
" <td>"
;
17.
str+=
" <span style=\" width:150px;display:block;white-space:nowrap; overflow:hidden; text-overflow:ellipsis;\">"
;
18.
str+=item.BaseRoomId;
19.
str+=
" </span>"
20.
str+=
" </td>"
;
21.
str+=
" <td>"
;
22.
str+=
" <span style=\" width:150px;display:block;white-space:nowrap; overflow:hidden; text-overflow:ellipsis;\">"
;
23.
str+=item.ShipId;
24.
str+=
" </span>"
25.
str+=
" </td>"
;
26.
str+=
" <td>"
;
27.
str+=
" <span style=\" width:150px;display:block;white-space:nowrap; overflow:hidden; text-overflow:ellipsis;\">"
;
28.
str+=item.RoomType;
29.
str+=
" </span>"
30.
str+=
" </td>"
;
31.
str+=
" <td>"
;
32.
str+=
" <span style=\" width:150px;display:block;white-space:nowrap; overflow:hidden; text-overflow:ellipsis;\">"
;
33.
str+=item.RoomName;
34.
str+=
" </span>"
35.
str+=
" </td>"
;
36.
str+=
"</tr>"
;
37.
$(
"#RoomInfoListTable"
).append(str); <br> });
38.
}
39.
});
40.
41.
}
(2)使用JQuery的Ajax 请求返回值为PartialView格式的Controller方法
假设有这样的一个Model:
1.
namespace MvcApplication1.Models
2.
{
3.
public
class
Team
4.
{
5.
public
string Preletter { get; set; }
6.
public
string Name { get; set; }
7.
}
8.
}
通过JQuery异步加载分部视图,Home/Index.cshtml:
01.
@{
02.
ViewBag.Title =
"Index"
;
03.
Layout =
"~/Views/Shared/_Layout.cshtml"
;
04.
}
05.
<h4>Index</h4>
06.
<div>
07.
<a href=
"#"
id=
"a"
>通过jQuery异步</a> <br/>
08.
</div>
09.
<div id=
"result"
>
10.
</div>
11.
@section
scripts
12.
{
13.
<script type=
"text/javascript"
>
14.
$(function() {
15.
$(
‘#a‘
).click(function() {
16.
$.ajax({
17.
url:
‘@Url.Action("Index","Home")‘
,
18.
data: { pre:
‘B‘
},
19.
type:
‘POST‘
,
20.
success: function(data) {
21.
22.
23.
$(
‘#result‘
).empty().append(data);
24.
25.
26.
}
27.
});
28.
29.
return
false
;
30.
});
31.
});
32.
</script>
33.
}
HomeController控制器中:
01.
using System.Collections.Generic;
02.
using System.Linq;
03.
using System.Web.Mvc;
04.
using MvcApplication1.Models;
05.
namespace MvcApplication1.Controllers
06.
{
07.
public
class
HomeController : Controller
08.
{
09.
public
ActionResult Index()
10.
{
11.
return
View();
12.
}
13.
[HttpPost]
14.
public
ActionResult Index(string pre)
15.
{
16.
var result = GetAllTeams().Where(t => t.Preletter == pre).ToList();
17.
ViewBag.msg =
"通过jQuery异步方式到达这里~~"
;
18.
return
PartialView(
"TeamY"
, result);
19.
}
20.
private
List<Team> GetAllTeams()
21.
{
22.
return
new
List<Team>()
23.
{
24.
new
Team(){Name =
"巴西队"
, Preletter =
"B"
},
25.
new
Team(){Name =
"克罗地亚队"
, Preletter =
"K"
},
26.
new
Team(){Name =
"巴拉圭"
, Preletter =
"B"
},
27.
new
Team(){Name =
"韩国"
, Preletter =
"K"
}
28.
};
29.
}
30.
}
31.
}
分部视图TeamY.cshtml:
01.
@model
IEnumerable<MvcApplication1.Models.Team>
02.
@{
03.
var result = string.Empty;
04.
foreach (var item in Model)
05.
{
06.
result += item.Name +
","
;
07.
}
08.
}
09.
@ViewBag
.msg.ToString()
10.
<br/>
11.
@result
.Substring(
0
,result.Length -
1
)
3、基于JQuery的表单异步提交
举个栗子吧:
1.
<script type=
"text/javascript"
>
2.
$(document).ready(function () {
3.
$(
"#form1"
).submit(function (event) {
4.
event.preventDefault();
//阻止默认提交事件,改用JS处理提交事件<br> $.ajax({<br> type:"Post//表单提交类型 <br> url: "@Url.Content("~/User/Create")",//表单提交的Action方法<br> data:$("#form1").serialize(), //序列化表单的值为字符串,前提是表单里边的输入标签都要有name属性才可以,序列化后的形式大概是这样的:a=1&b=2&c=3&d=4&e=5<br> success:function(msg){<br> $("#result").html(msg); <br> } <br> }); <br> return false;<br> }); <br>});
5.
</script>
但是我觉得如果表单提交的数据少的话,可以用这种,如果多的话,就没有必要了,用MVC自带的更好
三、如何提高Ajax性能
1、适当使用缓存机制
2、使用CDN内容分发来访问Jquery脚本:
(1)自己公司架设CDN服务器
(2)使用第三方公司的,比如微软,谷歌等公司的CDN,但有时候不太靠谱
3、JS/CSS文件的打包合并(Bundling)及压缩(Minification)
将多个JS或CSS文件打包合并成一个文件,并在网站发布之后进行压缩,从而减少HTTP请求次数,提高网络加载速度和页面解析速度。压缩功能实现了对javascript脚本和CSS进行压缩的功能,它能够去除脚本或样式中不必要的空白和注释,同时能够优化脚本变量名的长度
例如在BundleConfig.cs里面配置捆绑js和css文件:
01.
using System.Web;
02.
using System.Web.Optimization;
03.
04.
namespace MvcExample
05.
{
06.
public
class
BundleConfig
07.
{
08.
// For more information on Bundling, visit http://go.microsoft.com/fwlink/?LinkId=254725
09.
public
static
void
RegisterBundles(BundleCollection bundles)
10.
{
11.
bundles.Add(
new
ScriptBundle(
"~/bundles/jquery"
).Include(
12.
"~/Scripts/jquery-{version}.js"
));
13.
14.
bundles.Add(
new
StyleBundle(
"~/Content/css"
).Include(
"~/Content/site.css"
));
15.
}
16.
}
17.
}
记得在Global.asax中注册一下:
1.
BundleConfig.RegisterBundles(BundleTable.Bundles);
页面引用时可以这样引用:
01.
<!DOCTYPE html>
02.
<html>
03.
<head>
04.
<meta charset=
"utf-8"
/>
05.
<meta name=
"viewport"
content=
"width=device-width"
/>
06.
<title>
@ViewBag
.Title</title>
07.
@Styles
.Render(
"~/Content/css"
)
08.
@Scripts
.Render(
"~/bundles/jquery"
)
09.
@RenderSection
(
"scripts"
, required:
false
)
10.
</head>
11.
<body>
12.
@RenderBody
()
13.
</body>
14.
</html>
启用JS/CSS文件压缩合并:
Web.config中配置1.
<compilation debug=
"false"
targetFramework=
"4.0"
/>
1.
BundleTable.EnableOptimizations =
true
;
4、最好将js脚本文件放在view页面下面一点
关于ASP.NET MVC和Ajax的故事,暂且讲到这里吧!
标签:
原文地址:http://www.cnblogs.com/zjoch/p/4330219.html