简单来说Ajax是一个无需重新加载整个网页的情况下,可以更新局部页面或数据的技术(异步的发送接收数据,不会干扰当前页面)。
Ajax工作原理
Ajax使浏览器和服务器之间多了一个Ajax引擎作为中间层。通过Ajax请求服务器时,Ajax会自行判断哪些数据是需要提交到服务器,哪些不需要。只有确定需要从服务器读取新数据时,Ajax引擎才会向服务器提交请求。
Ajax几个特点
不需要提交整个页面就可以更新数据。
与服务器异步通信。
Ajax请求不能后退,浏览器没有历史记录。
Ajax请求的页面不能加入到收藏夹。
Jquery中的Ajax
JQuery 对 Ajax 做了大量的封装,不需要去考虑浏览器兼容性,使用起来也较为方便。
jquery对Ajax一共有三层封装。
最底层:$.ajax()。
第二层:.load()、$.get()和$.post()。
最高层: $.getScript()和$.getJSON()方法。
$.Ajax()
$.Ajax()是所有Ajax方法中最底层的方法,其他的都是基于$.Ajax()方法的封装,该方法只有一个参数-
JQueryAjaxSettings
(功能键值对)。
$.Ajax
参数
JQueryAjaxSettings
介绍:
$.get()和$.post()
.load()
一般在获取静态资源时调用,
$.get()
和
$.post()
方法在需要和服务器交互数据时调用。
$.get()
方法通过 HTTP GET 请求载入信息。
这是
$.ajax
GET请求的简写方式。请求成功时可调用回调函数。
$.get(url,data,success(response,status,xhr),dataType)
使用$.get()
从服务端获取数据-代码示例
定义model
public class PersonViewModel
public int PersonID { get; set; }
public string Name { get; set; }
public string PhoneNum { get; set; }
public bool IsMarried{get;set;}
定义Controller Action
public class MyAjaxController : Controller
public JsonResult PersonList()
IList<PersonViewModel> persons = new List<PersonViewModel>();
for (int i = 0; i < 10; i++)
persons.Add(new PersonViewModel() { Email = "email" + i, Name = "name", IsMarried = false, PhoneNum = "1234" + i, Home = CityEnum.BJ, Height = i });
return Json(persons,JsonRequestBehavior.AllowGet);
定义View
$.get('@Url.Action("PersonList", "MyAjax")',function (result) {
$.each(result, function (index, person) {
$('#myDiv').append('<p>Id: ' + person.PersonID + '</p>' +
'<p>Name: ' + person.Name + '</p>');
//在Jquery1.5版本后,新增了一些事件,可以更好的处理不同结果。
$.get('@Url.Action("PersonList", "MyAjax")')
.done(function (data) {
$.each(data, function (index, person) {
$('#myDiv').append('<p>Id: ' + person.PersonID + '</p>' +
'<p>Id: ' + person.Name + '</p>');
.fail(function (data) {
alert(data);
$.post()
方法通过 HTTP POST 请求从服务器载入数据。
$.post(url,data,success(data, textStatus, jqXHR),dataType)
使用$.post()
方法向服务端发送数据-代码示例
定义一个Action
[HttpPost]
public JsonResult ToPersonList(IEnumerable<PersonViewModel> persons)
if (persons != null)
return Json(true);
else return Json(false);
定义一个View
<script>
var results = { persons : [{ "PersonID": "1", "Name": "Manas" },
{ "PersonID": "2", "Name": "Tester" }] };
$.post('@Url.Action("ToPersonList","MyAjax")',results, function (data) {
alert(data)
//同样也可以使用Jquery1.5版本的新的事件
$.post('@Url.Action("ToPersonList","MyAjax")', results)
.done(function (data) {
alert(data);
.fail(function (data) {
alert(data);
.always(function (data) {
alert(data);
</script>
$.get()
$.post()
方法都是四个参数,前面三个参数和$.load()
一样,最后一个参数dataType:服务器返回的数据格式:xml、html、script、json、jsonp和text。只有第一个参数是必须的,其他都可以为空。
$.get()
$.post()
都是$.ajax()
的一个简写封装,都是只能回调success状态,error,和complete不能被回调。但是在jquery1.5版本上,新加了jqXHR.done()
(表示成功), jqXHR.fail()
(表示错误), 和 jqXHR.always()
事件,可以实现不同状态的回调。
表单序列化
如果我们有一个复杂的表单,一个一个获取表单数据是一个很琐碎的事。jquery提供了一个表单的序列化方法serialize()
,会智能的获取指定表单内的所有元素(包括单选框,复选框,下拉列表等)把表单内容序列化为字符串。此外serializeArray()
方法可以把数据整合为键值对的json对象。
如果我们需要多次调用$.ajax
方法,并且很多参数都相同,可以使用$.ajaxSetup()
方法,它会把一些公共的参数预先设置好,不用每次都设置。
$('form input[type=button]').click(function () {
$.ajaxSetup({
type : 'POST',
url : 'test',
data : $('form').serialize()
$.ajax({
success : function (response, status, xhr) {
alert(response);
在使用 data
属性传递数据的时候,如果是以对象形式传递键值对,可以使用$.param()
方法将对象转换为字符串键值对格式。
(主要是针对无法直接使用表单序列化方法.serialize()
,且传递参数为对象的情况)
MVC中的Ajax使用
Asp.Net MVC中包含了一组Ajax辅助方法。可以用来创建异步执行的表单和指向控制器操作的异步链接。当使用这个辅助方法时,不用编写任何脚本代码来实现程序的异步。该辅助方法依赖于非侵入式MVC的jquery扩展。如果使用这些辅助方法时,需要引入脚本jquery.unbotrusive-ajax.js
(可以在NuGet中获得)
Asp.Net MVC中的分部页面可以是partialPage
也可以是含有布局(layout
)的完整页面。只是在return的时候返回类型是PartialView
。
绝大部分情况下,部分页面的请求和完整页面的请求是一样的流程-请求被路由到指定控制器,控制器执行特定的业务逻辑,返回给对应的试图。 我们可以在控制器中使用Request.IsAjax
来区别是否是ajax请求,是否是要返回分部试图,还是完整试图。分部试图(return PartialView)是render和返回了该页面的html。但是完整试图(return View)是返回了包括页面资源(css,js)和布局的所有html。
Ajax.Load()
异步加载一个分布页面
定义一个ViewModel
//Model
[Bind(Exclude = "PersonID")]
public class PersonViewModel
[ScaffoldColumn(false)]
public int PersonID { get; set; }
[Display(Name = "姓名")]
[Required(ErrorMessage = "不能为空")]
public string Name { get; set; }
[Display(Name = "手机号")]
[Required(ErrorMessage = "不能为空")]
[DataType(DataType.PhoneNumber)]
public string PhoneNum { get; set; }
public bool IsMarried{get;set;}
定义主页面View
//Main View:
ViewBag.Title = "主页面";
<h2>主页面</h2>
<p>列表详细信息</p>
<div id="partialDiv"></div>
<script>
$('#partialDiv').load('@Url.Action("ListPage", "MyAjax")')
</script>
定义分部页面View
//分部页面
ViewBag.Title = "ListPage";
@model IList<WebApp.Models.PersonViewModel>
<h2>分布页</h2>
<table class="table table-striped">
<thead>
@{ WebApp.Models.PersonViewModel p = null;}
<th>@Html.LabelFor(m => @p.Email)</th>
<th>@Html.LabelFor(m => @p.Name)</th>
<th>@Html.LabelFor(m => @p.Home)</th>
<th>@Html.LabelFor(m => @p.IsMarried)</th>
<th>@Html.LabelFor(m => @p.Height)</th>
<th>@Html.LabelFor(m => @p.PhoneNum)</th>
@*也可以使用DisplayNameFor来显示表头*@
@*<th>@Html.DisplayNameFor(m => Model[0].Email)</th>
<th>@Html.DisplayNameFor(m => Model[0].Name)</th>
<th>@Html.DisplayNameFor(m => Model[0].IsMarried)</th>
<th>@Html.DisplayNameFor(m => Model[0].Height)</th>
<th>@Html.DisplayNameFor(m => Model[0].PhoneNum)</th>*@
</thead>
<tbody>
@foreach (var item in Model)
<td>@item.Email</td>
<td>@item.Name</td>
<td>@item.Home</td>
<td>@item.IsMarried</td>
<td>@item.Height</td>
<td>@item.PhoneNum</td>
</tbody>
</table>
定义一个Action
//Controller
public class MyAjaxController : Controller
//主页面
public ActionResult MainPage()
return View();
//分部页面
public ActionResult ListPage()
IList<PersonViewModel> persons = new List<PersonViewModel>();
for (int i = 0; i < 10; i++)
persons.Add(new PersonViewModel() { Email = "email" + i, Name = "name", IsMarried = false, PhoneNum = "1234" + i, Home = CityEnum.BJ, Height = i });
if (Request.IsAjaxRequest())
return PartialView(persons);
return View(persons);
当请求主页面的时候,会把分布页面异步加载到主页面的<div id="partialDiv"></div>
里
Ajax.ActionLink()
Ajax.ActionLink()辅助方法,可以异步请求加载页面。
//Main view 主页面
ViewBag.Title = "MainPage";
<h2>主页面</h2>
<p>列表详细信息</p>
@Ajax.ActionLink("加载详细列表", "ListPage", new AjaxOptions { UpdateTargetId = "partialDiv", InsertionMode = InsertionMode.Replace, HttpMethod = "Get" })
<div id="partialDiv"></div>
Asp.Net MVC 提供了多个AjaxOptions
的属性,方法给我们使用,免去了不少js代码。
InsertionModel
获取或设置指定如何将响应插入目标 DOM 元素的模式。插入模式(“InsertAfter”、“InsertBefore”或“Replace”)。 默认值为“Replace”。
LoadingElementDuration
获取或设置一个值(以毫秒为单位),该值控制在显示或隐藏加载元素时的动画持续时间。
LoadingElementId
获取或设置在加载 Ajax 函数时要显示的 HTML 元素的 id 特性。
OnBegin
获取或设置要在更新页面之前立即调用的 JavaScript 函数的名称
OnComplete
获取或设置在实例化响应数据之后但在更新页面之前,要调用的 JavaScript 函数。
OnFailure
获取或设置在页面更新失败时要调用的 JavaScript 函数。
OnSuccess
获取或设置在成功更新页面之后要调用的 JavaScript 函数。
UpdateTargetId
获取或设置要使用服务器响应来更新的 DOM 元素的 ID。
获取或设置要向其发送请求的 URL。
Ajax表单提交
当我们使用jquery的ajax提交表单时,需要在click事件中添加e.preventDefault()
或者把<input type="submit" value="提交" />
改为<input type="button" value="提交" />
。否则会刷新页面。如下代码所示,
<form class="form-horizontal" role="form" method="post" id="myform">
<label for="i1">第一</label>
<input type="text" name="i1" id="i1" />
<label for="i2">第二</label>
<input type="text" name="i2" id="i2" />
<label for="i3">第三</label>
<input type="text" name="i3" id="i3" />
//或者使用<input type="button" value="提交" />,不必再阻止事件的传递了。
<input type="submit" value="提交" />
</form>
<script>
$("input[type=submit]").click(function (e) {
e.preventDefault();//阻止事件传递
$.post("@Url.Action("CheckNameByAjax")", $("#myform").serialize(), function (result) {
alert(result);
</script>
Asp.Net MVC提供了Ajax的表单辅助方法,可以更简单快速的实现表单的ajax提交。
@using (Ajax.BeginForm("AjaxForm", "MyAjax", new AjaxOptions { HttpMethod = "Post", OnComplete = "foo", OnSuccess = "succ", OnFailure = "fail" }, new { role = "form" }))
<label for="i1">第一</label>
<input type="text" name="i1" id="i1" />
<label for="i2">第二</label>
<input type="text" name="i2" id="i2" />
<label for="i3">第三</label>
<input type="text" name="i3" id="i3" />
<input type="submit" value="提交" />
Ajax数据验证
在注册有时需要保证用户名或者邮箱唯一或者是否合法,这个验证又必须放在服务端完成。可以使用ajax异步请求,在用户添加完用户名或者邮箱的时候立即在服务端验证并告知用户结果,而不用填完整个表单,再去验证唯一合法性。
定义一个ViewModel
//Model
[Bind(Exclude = "PersonID")]
public class PersonViewModel
[ScaffoldColumn(false)]
public int PersonID { get; set; }
[Display(Name = "姓名")]
[Required(ErrorMessage = "不能为空")]
public string Name { get; set; }
[Display(Name = "手机号")]
[Required(ErrorMessage = "不能为空")]
[DataType(DataType.PhoneNumber)]
public string PhoneNum { get; set; }
定义试图View
//view
@model NameSpace.PersonViewModel
<form class="form-horizontal" role="form" method="post" id="myform">
<div class="form-group">
@Html.LabelFor(m => m.Name, new { @class = "control-label col-md-3" })
<div class="col-md-9">
@Html.TextBoxFor(m => m.Name, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Name, "", new { @class = "text-danger" })
<input type="submit" value="提交" class="btn btn-success" id="sure" />
</form>
<script>
$("#Name").change(function () {
$.ajax({
url: "@Url.Action("CheckUserName")",
type: "post",
data: { Name: $("#Name").val() },
dataType: "JSON",
success: function (response, stutas, xhr) {
alert(response+status + xhr.statusText);
error: function (xhr, stutas, response) {
alert(response + status + xhr.statusText);
complete: function (data) {
alert(data.status+data);
</script>
定义一个Action校验用户名的唯一和合法性
[HttpPost]
//参数一定要和ViewModel的属性名称一致
public JsonResult CheckUserName(string Name)
bool result = true;
if (Name == "admin")
result = false;
return Json(result);
至此我们实现了Ajax的用户名唯一性和合法性的校验。但是 Asp.Net MVC 提供了一个更简单的方法,可以用更少的代码实现一样的功能
在属性上添加[Remote("MethodName", "ControllerName")]
特性
该特性允许客户端调用服务端的方法。
修改Model
[Bind(Exclude = "PersonID")]
public class PersonViewModel
[ScaffoldColumn(false)]
public int PersonID { get; set; }
[Display(Name = "姓名")]
//添加Remote特性
[Remote("CheckUserName", "ControllerName",ErrorMessage="用户名已存在")]
[Required(ErrorMessage = "不能为空")]
public string Name { get; set; }
[Display(Name = "手机号")]
[Required(ErrorMessage = "不能为空")]
[DataType(DataType.PhoneNumber)]
public string PhoneNum { get; set; }
我们只需添加一个Remote特性就可以实现用户名的服务端验证。节省了js的代码。
修改Action
Asp.Net MVC默认是不允许Get请求Json(防止Json被劫持)。所以如果你需要Get请求Json。必须添加JsonRequestBehavior.AllowGet
。且该数据不那么重要。
//Action
public JsonResult CheckUserName(string Name)
//参数一定要和属性名称一致
bool result = true;
if (Name == "admin")
result = false;
//添加JsonRequestBehavior.AllowGet
return Json(result, JsonRequestBehavior.AllowGet);
Asp.Net MVC Ajax辅助方法可以让我们更简便的使用Ajax。但是也要理解本身Ajajx的请求。
如有不对,请多多指教。
参考资料: