Asp.Net MVC 使用 Ajax

Ajax

简单来说Ajax是一个无需重新加载整个网页的情况下,可以更新局部页面或数据的技术(异步的发送接收数据,不会干扰当前页面)。

Ajax工作原理

Ajax使浏览器和服务器之间多了一个Ajax引擎作为中间层。通过Ajax请求服务器时,Ajax会自行判断哪些数据是需要提交到服务器,哪些不需要。只有确定需要从服务器读取新数据时,Ajax引擎才会向服务器提交请求。

Ajax几个特点

  1. 不需要提交整个页面就可以更新数据。
  2. 与服务器异步通信。
  3. Ajax请求不能后退,浏览器没有历史记录。
  4. Ajax请求的页面不能加入到收藏夹。

Jquery中的Ajax

JQuery 对 Ajax 做了大量的封装,不需要去考虑浏览器兼容性,使用起来也较为方便。

jquery对Ajax一共有三层封装。

  • 最底层:$.ajax()。

  • 第二层:.load()、$.get()和$.post()。

  • 最高层: $.getScript()和$.getJSON()方法。


$.Ajax()

$.Ajax()是所有Ajax方法中最底层的方法,其他的都是基于$.Ajax()方法的封装,该方法只有一个参数-JQueryAjaxSettings(功能键值对)。

$.Ajax参数JQueryAjaxSettings介绍:

参数 类型 说明
url String 请求的地址
type String 请求方式:POST 或 GET,默认 GET
timeout Number 设置请求超时的时间(毫秒)
data Object或String 发送到服务器的数据,键值对或字符串
dataType String 从服务器返回的数据类型,比如 html、xml、json 等
beforeSend Function 发送请求前可修改 XMLHttpRequest 对象的函数
complete Function 请求完成后调用的回调函数
success Function 请求成功后调用的回调函数,先执行success再执行complete
error Function 请求失败时调用的回调函数,先执行error再执行complete
global Boolean 默认为 true,表示是否触发全局 Ajax
cache Boolean 设置浏览器缓存响应,默认为 true。如果 dataType类型为 script 或 jsonp 则为 false。
content DOM 指定某个元素为与这个请求相关的所有回调函数的上下文。
contentType String 指 定 请 求 内 容 的 类 型 。 默 认 为application/x-www-form-urlencoded。
async Boolean 是否异步处理。默认为 true,false 为同步处理
processData Boolean 默认为 true,数据被处理为 URL 编码格式。如果为 false,则阻止将传入的数据处理为 URL 编码的格式。
dataFilter Function 用来筛选响应数据的回调函数。
ifModified Boolean 默认为 false,不进行头检测。如果为true,进行头检测,当相应内容与上次请求改变时,请求被认为是成功的。
jsonp String 指定一个查询参数名称来覆盖默认的 jsonp 回调参数名 callback。
username String 在 HTTP 认证请求中使用的用户名
password String 在 HTTP 认证请求中使用的密码
scriptCharset String 当远程和本地内容使用不同的字符集时,用来设置 script 和 jsonp 请求所使用的字符集。
xhr Function 用来提供 XHR 实例自定义实现的回调函数
traditional Boolean 默认为 false,不使用传统风格的参数序列化。如为 true,则使用

代码示例:

$('button').click(function(){
$.ajax(
{
type:'post',
url:'test',
data:{
url:'hello',
},
dataType:'json',
success:function(data,stutas,xhr){
alert(data);
},
error:function(xhr, textStatus, data)){
alert(data);
},
complete:function(xhr,textStatus){
alert(textStatus);
}
}
)
});

$.Ajax的回调函数介绍:

  • success

Function( Anything data, String textStatus, jqXHR jqXHR )

请求成功后执行的回调函数。

参数 类型 说明
data anything 从服务器返回的数据,并根据dataType参数类型处理后的数据(默认是json)
textStatus string 描述状态的字符串
jqxhr jqXHR XMLHTTPRequest对象
  • error

Function( jqXHR jqXHR, String textStatus, String errorThrown )

请求失败是执行的回调函数

参数 类型 说明
errorThrown string HTTP状态的文本部分
textStatus string 描述错误信息的字符串
jqxhr jqXHR 描述发生错误类型的一个字符串 和 捕获的异常对象
  • complete

Function( jqXHR jqXHR, String textStatus )

请求完成后执行的回调函数,不管是成功还是失败都执行。

参数 类型 说明
errorThrown string HTTP状态的文本部分
textStatus string 描述请求状态的字符串
jqxhr jqXHR XMLHTTPRequest对象

$.load()

从服务器获取数据并且将返回的HTML代码插入至匹配的元素中。

$('Element').load(url,data,success(responseText,textStatus,XMLHttpRequest))
参数 类型 说明
url string 必须 请求地址
data Json或者string 可选 请求数据 如果是json该load方法是post请求,默认是get请求
success function 当请求成功后执行的回调函数
responseText string 获得字符串形式的响应数据
textStatus string 文本方式返回HTTP状态码
XMLHttpRequest Object xhr对象,有多种属性

$.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;}
<tr>
<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>*@
</tr> </thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>@item.Email</td>
<td>@item.Name</td>
<td>@item.Home</td>
<td>@item.IsMarried</td>
<td>@item.Height</td>
<td>@item.PhoneNum</td>
</tr>
}
</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代码。

名称 说明
Confirm 获取或设置在提交请求之前显示在确认窗口中的消息。
HttpMethod 获取或设置 HTTP 请求方法(“Get”或“Post”)。
InsertionModel 获取或设置指定如何将响应插入目标 DOM 元素的模式。插入模式(“InsertAfter”、“InsertBefore”或“Replace”)。 默认值为“Replace”。
LoadingElementDuration 获取或设置一个值(以毫秒为单位),该值控制在显示或隐藏加载元素时的动画持续时间。
LoadingElementId 获取或设置在加载 Ajax 函数时要显示的 HTML 元素的 id 特性。
OnBegin 获取或设置要在更新页面之前立即调用的 JavaScript 函数的名称
OnComplete 获取或设置在实例化响应数据之后但在更新页面之前,要调用的 JavaScript 函数。
OnFailure 获取或设置在页面更新失败时要调用的 JavaScript 函数。
OnSuccess 获取或设置在成功更新页面之后要调用的 JavaScript 函数。
UpdateTargetId 获取或设置要使用服务器响应来更新的 DOM 元素的 ID。
Url 获取或设置要向其发送请求的 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">
<div>
<label for="i1">第一</label>
<input type="text" name="i1" id="i1" />
</div>
<div>
<label for="i2">第二</label>
<input type="text" name="i2" id="i2" />
</div>
<div>
<label for="i3">第三</label>
<input type="text" name="i3" id="i3" />
</div>
//或者使用<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" }))
{
<div>
<label for="i1">第一</label>
<input type="text" name="i1" id="i1" />
</div>
<div>
<label for="i2">第二</label>
<input type="text" name="i2" id="i2" />
</div>
<div>
<label for="i3">第三</label>
<input type="text" name="i3" id="i3" />
</div>
<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>
<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" })
</div>
</div>
<div>
<input type="submit" value="提交" class="btn btn-success" id="sure" />
</div>
</div>
</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的请求。


如有不对,请多多指教。


参考资料:

Asp.Net MVC 使用 Ajax的更多相关文章

  1. ASP.NET MVC 实现AJAX跨域请求方法《1》

    ASP.NET MVC 实现AJAX跨域请求的两种方法 通常发送AJAX请求都是在本域内完成的,也就是向本域内的某个URL发送请求,完成部分页面的刷新.但有的时候需要向其它域发送AJAX请求,完成数据 ...

  2. asp.net mvc 使用ajax请求 控制器 (PartialViewResult)分部的action,得到一个分部视图(PartialView)的HTML,进行渲染

    在asp.net mvc 使用ajax请求获取数据的时候,我们一般是返回json或者xml,然后解析这些数据进行渲染,这样会比较麻烦,可以请求一个 分部action,返回一个分部视图 直接可以渲染,不 ...

  3. 在Asp.Net MVC中用Ajax回调后台方法

    在Asp.Net MVC中用Ajax回调后台方法基本格式: var operData = ...; //传递的参数(action中定义的) var type = ...; //传递的参数(action ...

  4. [代码示例]用Fine Uploader+ASP.NET MVC实现ajax文件上传

    原文 [代码示例]用Fine Uploader+ASP.NET MVC实现ajax文件上传 Fine Uploader(http://fineuploader.com/)是一个实现 ajax 上传文件 ...

  5. Asp.Net MVC Unobtrusive Ajax

    1.   Unobtrusive JavaScript介绍 说到Unobtrusive Ajax,就要谈谈UnobtrusiveJavaScript了,所谓Unobtrusive JavaScript ...

  6. ASP.NET MVC之Ajax如影随行

    一.Ajax的前世今生 我一直觉得google是一家牛逼的公司,为什么这样说呢?<舌尖上的中国>大家都看了,那些美食估计你是百看不厌,但是里边我觉得其实也有这样的一个哲学:关于食材,对于种 ...

  7. ASP.NET MVC 实现 AJAX 跨域请求

    ASP.NET MVC 实现AJAX跨域请求的两种方法 和大家分享下Ajax 跨域的经验,之前也找了好多资料,但是都不行,后来看到个可行的修改了并测试下 果然OK了   希望对大家有所帮助! 通常发送 ...

  8. ASP.NET MVC 学习笔记-7.自定义配置信息 ASP.NET MVC 学习笔记-6.异步控制器 ASP.NET MVC 学习笔记-5.Controller与View的数据传递 ASP.NET MVC 学习笔记-4.ASP.NET MVC中Ajax的应用 ASP.NET MVC 学习笔记-3.面向对象设计原则

    ASP.NET MVC 学习笔记-7.自定义配置信息   ASP.NET程序中的web.config文件中,在appSettings这个配置节中能够保存一些配置,比如, 1 <appSettin ...

  9. Asp.net MVC 中Ajax的使用 [分享]

    文章转自 http://www.huiyoumi.wang/upload/forum.php?mod=viewthread&tid=75&extra= Asp.net MVC 抛弃了A ...

随机推荐

  1. Codeforces Round #432 (Div. 2, based on IndiaHacks Final Round 2017)ABCD

    A. Arpa and a research in Mexican wave time limit per test 1 second memory limit per test 256 megaby ...

  2. 推荐系统相关算法(1):SVD

    假如要预测Zero君对一部电影M的评分,而手上只有Zero君对若干部电影的评分和风炎君对若干部电影的评分(包含M的评分).那么能预测出Zero君对M的评分吗?答案显然是能.最简单的方法就是直接将预测分 ...

  3. 一脸懵逼学习基于CentOs的Hadoop集群安装与配置

    1:Hadoop分布式计算平台是由Apache软件基金会开发的一个开源分布式计算平台.以Hadoop分布式文件系统(HDFS)和MapReduce(Google MapReduce的开源实现)为核心的 ...

  4. sqlserver 缩小表空间

    1. 保留需要的数据之新表中->TRUNCATE原表数据->还原之前保留的数据之原表中->压缩表空间 脚本类似如下 SELECT * INTO #keep FROM Original ...

  5. DotNetCore跨平台~配置文件与配置代码如何共存

    回到目录 古人云<一山不容二虎>,而进行dotnet core时代之后,我们可以看到这样的一些官方的DEMO,它将数据连接串和其它配置项都直接硬编码在代码里,即在startup中进行定义, ...

  6. Python通过future处理并发

    future初识 通过下面脚本来对future进行一个初步了解:例子1:普通通过循环的方式 import os import time import sys import requests POP20 ...

  7. VB6文件操作自定义函数合集之一

    '--与文件及文件夹操作相关的函数 '--必须引用FSO的ACTIVE OBJECT Dim strList As String '--列表串,返回文件列表 '================ '-- ...

  8. Java集合框架,未完

    一.集合类 集合的由来: 面向对象语言对事物的体现都是以对象的形式,为了方便对多个对象的操作,就需要将对象进行存储,集合就是存储对象最常用的一种方式. 集合特点:1,用于存储对象的容器.(容器本身就是 ...

  9. ASP.NET没有魔法——ASP.NET MVC IoC

    之前的文章介绍了MVC如何通过ControllerFactory及ControllerActivator创建Controller,而Controller又是如何通过ControllerBase这个模板 ...

  10. 测试中出现ERROR StatusLogger No log4j2 configuration file

    概述 在hibernate框架搭建完成用log4j2进行测试时,总是出现ERROR StatusLogger No log4j2 configuration file found. Using def ...