本节内容:javascript
执行一个AJAX调用在如今的应用里很是常见,尤为在SPAs(Single-Page Applications 单页面应用)里,它几乎是惟一与服务器通讯的方式。一个AJAX调用由几个重复的步骤组成:java
在客户端,基本上,javascript代码应该提供一个URL,随意的一个数据和选择一个方法(POST,GET...)来执行一个AJAX调用,它必须等待并处理返回值,当向服务器执行一个调用时,可能会出错(一般网络错误),或其它服务端错误,服务端返回一个携带错误信息的失败的响应,客户端应该处理这些或通知用户(可显示一个错误对话框),若是没有错误,服务端发送一个返回数据,客户端也必须处理它。操做过程当中,一般会屏蔽或整个屏幕并显示一个AJAX正在操做的信息,直到它完成。jquery
服务端代码获取到一个请求,执行一些服务端代码,捕获任何的异常并返回一个有效的返回给客户端。若是有出错的状况,可能会发送错误信息给客户端,若是是一个验证错误,服务器可能会添加一个验证问题。若是成功,可能会发送一个返回值给客户端。ajax
ABP使用经过包装了AJAX调用的abp.ajax,自动处理这些步骤,下面是一个AJAX调用示例:json
var newPerson = { name: 'Dougles Adams', age: 42 }; abp.ajax({ url: '/People/SavePerson', data: JSON.stringify(newPerson) }).done(function(data) { abp.notify.success('created new person with id = ' + data.personId); });
abp.ajax获取一个可选的对象,你能够传递任何的参数(它会被jQuery的$.ajax方式验证),此处有些默认:dataType:'json',type:'POST',contentType:'application/json'(因此,在发送到服务器前,咱们调用JSON.stringify把javascript转换为JSON字符串),咱们能够给abp.ajax传递options来覆盖这些默认.api
abp.ajax返回promise,因此,你能够写done,fail,then....处理程序,在这个例子中,咱们建立了一个简单的AJAX请求,调用PeopleController的SavePerson操做,在done处理程序里,咱们获取数据库里新建立的person的id并显示一个成功的通知(查看notification API)。咱们看一下这个AJAX调用的MVC控制器:promise
public class PeopleController : AbpController { [HttpPost] public JsonResult SavePerson(SavePersonModel person) { //TODO: save new person to database and return new person's id return Json(new {PersonId = 42}); } }
SavePersonModel包含Name和Age属性,SavePerson标记为HttpPost,所以abp.ajax的默认方法为POST。我简化方法的实现,只返回一个匿名对象。服务器
这样直截了当,但有些重要的东西ABP在背后进行了处理,让咱们深刻细节...
即便咱们返回一个PersonId=2对象,ABP把它包装成一个MvcAjaxResponse对象,AJAX响应实质上像下面这样:
{ "success": true, "result": { "personId": 42 }, "error": null, "targetUrl": null, "unAuthorizedRequest": false, "__abp": true }
此处,全部属性都是小骆峰式命名(由于这是javascript世界里约定好的),即便它们在服务端是大骆峰式命名。让咱们解释一下这些属性:
[HttpPost] [DisableAuditing] public async Task<JsonResult> Login(LoginViewModel loginModel, string returnUrl = "", string returnUrlHash = "") { CheckModelState(); var loginResult = await GetLoginResultAsync( loginModel.UsernameOrEmailAddress, loginModel.Password, loginModel.TenancyName ); await SignInAsync(loginResult.User, loginResult.Identity, loginModel.RememberMe); if (string.IsNullOrWhiteSpace(returnUrl)) { returnUrl = Request.ApplicationPath; } if (!string.IsNullOrWhiteSpace(returnUrlHash)) { returnUrl = returnUrl + returnUrlHash; } return Json(new AjaxResponse { TargetUrl = returnUrl}); }
handleTargetUrl: function (targetUrl) { if (!targetUrl) { location.href = abp.appPath; } else { location.href = targetUrl; } },
abp.ajax函数识别和处理这个返回格式,若是不出错,abp.ajax里你的done处理程序获取真正的控制器的返回值(一个包含personId属性的对象)。
如上所述,ABP在服务器处理异常并返回一个包含错误信息的对象:
{ "targetUrl": null, "result": null, "success": false, "error": { "message": "An internal error occured during your request!", "details": "..." }, "unAuthorizedRequest": false, "__abp": true }
如你所见,success为false且result为null,abp.ajax处理这个对象且经过abp.message.error函数显示一个错误信息给用户。若是服务端抛出一个userFriendlyException类型的异常,它直接给用户显示错误信息,不然,它隐藏实际错误(把错误写到日志)并显示一个“发生一个内部错误..."信息给用户,这些ABP都会自动处理。
你可能会想为某些特定的AJAX调用,禁止显示信息,此时你能够把abpHandleError:false添加到abp.ajax的options里。
ABP为异常返回给定的状态码:
你能够经过为一个操做或控制器的全部操做使用WrapResult和DontWrapResult特性来控制包装。
若是Asp.net Mvc 操做方法返回类型为JsonResult(或异步的Task<JsonResult>),ABP默认地会进行包装(如上所述),你能够使用WrapResult特性改变这种行为,以下所示:
public class PeopleController : AbpController { [HttpPost] [WrapResult(WrapOnSuccess = false, WrapOnError = false)] public JsonResult SavePerson(SavePersonModel person) { //TODO: save new person to database and return new person's id return Json(new {PersonId = 42}); } }
做为快捷方式,咱们能够仅使用[DontWrapResult]来达到与此例相同目的。
你能够从启动配置(使用Configuration.Modules.AbpMvc()...)改变这种默认行为。
ABP默认状况下不包装成功的Web Api操做的结果,若是有须要,你能够添加WrapResult到操做或控制器上,可是默认包装异常。
你能够从启动配置(使用Configuration.Modules.AbpWebApi()...)改变这种默认行为。
ABP默认状况下包装动态Web Api层的方法结果,你能够经过在你的应用服务接口上使用WrapResult和DontWrapResult特性来改这种行为。
ABP自动包装JsonResult、ObjectResult和任何未实现IActionResult的结果,更多信息查看Asp.net Core 文档。
你能够从启动配置(使用Configuration.Modules.AbpAspNetCore()...)改变这种默认行为。
虽然ABP提供了一种简单使用AJAX的机制,但在一个真实世界的应用里,为每一个AJAX调用写一个javascript函数仍是很典型的,例如:
//Create a function to abstract AJAX call var savePerson = function(person) { return abp.ajax({ url: '/People/SavePerson', data: JSON.stringify(person) }); }; //Create a new person var newPerson = { name: 'Dougles Adams', age: 42 }; //Save the person savePerson(newPerson).done(function(data) { abp.notify.success('created new person with id = ' + data.personId); });
为每一个AJAX调用写一个函数,这是一个好的实践,但耗时且无趣, ABP能够自动地为应用服务和控制器生成这些类型的函数。
查阅动态Web Api层文档获取更多Web Api信息,查阅Asp.net Core文档获取有关Asp.net Core集成信息。
kid1412附:英文原文:http://www.aspnetboilerplate.com/Pages/Documents/Javascript-API/AJAX