博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ABP文档 - Javascript Api - AJAX
阅读量:6248 次
发布时间:2019-06-22

本文共 5603 字,大约阅读时间需要 18 分钟。

本节内容:

 

AJAX操作相关问题

执行一个AJAX调用在现在的应用里非常常见,尤其在SPAs(Single-Page Applications 单页面应用)里,它几乎是唯一与服务器通信的方式。一个AJAX调用由几个重复的步骤组成:

在客户端,基本上,javascript代码应该提供一个URL,随意的一个数据和选择一个方法(POST,GET...)来执行一个AJAX调用,它必须等待并处理返回值,当向服务器执行一个调用时,可能会出错(通常网络错误),或其它服务端错误,服务端返回一个携带错误信息的失败的响应,客户端应该处理这些或通知用户(可显示一个错误对话框),如果没有错误,服务端发送一个返回数据,客户端也必须处理它。操作过程中,通常会屏蔽或整个屏幕并显示一个AJAX正在操作的信息,直到它完成。

服务端代码获取到一个请求,执行一些服务端代码,捕获任何的异常并返回一个有效的返回给客户端。如果有出错的情况,可能会发送错误信息给客户端,如果是一个验证错误,服务器可能会添加一个验证问题。如果成功,可能会发送一个返回值给客户端。

 

ABP的方式

ABP使用通过包装了AJAX调用的abp.ajax,自动处理这些步骤,下面是一个AJAX调用示例:

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来覆盖这些默认.

abp.ajax返回,所以,你可以写done,fail,then....处理程序,在这个例子中,我们创建了一个简单的AJAX请求,调用PeopleController的SavePerson操作,在done处理程序里,我们获取数据库里新创建的person的id并显示一个成功的通知(查看)。我们看一下这个AJAX调用的MVC控制器:

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在背后进行了处理,让我们深入细节...

 

AJAX 返回信息

即使我们返回一个PersonId=2对象,ABP把它包装成一个MvcAjaxResponse对象,AJAX响应实质上像下面这样:

{  "success": true,  "result": {    "personId": 42  },  "error": null,  "targetUrl": null,  "unAuthorizedRequest": false,  "__abp": true}

此处,所有属性都是小骆峰式命名(因为这是javascript世界里约定好的),即使它们在服务端是大骆峰式命名。让我们解释一下这些属性:

  • success:一个布尔值(true或false),指示操作的是否成功,如果为true,abp.ajax解板promise并调用done处理程序,如果为false(如果有方法调用中抛出异常),它调用fail处理程序,并使用函数显示error信息。
  • result:返回控制器里操作的结果,如果success为true时服务器发送一个返回值后,它才可用。
  • error:如果success为false,这个属性包含一个错误明细信息的对象。
  • targetUrl:提供一个URL给服务端,在有需要的时候,把客户端定向到这个URL。kid1412注(ABP版本为1.0-1.1):此处列出模板生成的登录里含有的targetUrl的示例代码,另外迷惑人的是:生成的Login.cshtml里包含登录的Form,和“登录”的submit按钮,但它真正起作用的是Login.js里的点击事件里ajax,代码如下:
  • [HttpPost]        [DisableAuditing]        public async Task
    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}); }
    View Code
    返回的结果会在abp.jquery.js里处理,并被重定向到targetUrl:
    handleTargetUrl: function (targetUrl) {            if (!targetUrl) {                location.href = abp.appPath;            } else {                location.href = targetUrl;            }        },
    View Code
  • unAuthorizedRequest:服务端给客户端一个通知:这个操作未被认证或用户未被认证。如果为true,abp.ajax重新载入当前页面。
  • _abp:一个特殊的标志,表示响应是ABP包装的,你不需要使用它,abp.ajax会处理它。

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里。

 

HTTP 状态码

ABP为异常返回给定的状态码:

  • 401为未认证的请求(使用者未登录,但服务端操作需要认证)。
  • 403为未授权的请求。
  • 500为所有其它类型的异常。

 

WrapResult和DontWrapResult特性

你可以通过为一个操作或控制器的所有操作使用WrapResult和DontWrapResult特性来控制包装。

 

Asp.net Mvc 控制器

如果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()...)改变这种默认行为。

 

Asp.net Web Api 控制器

ABP默认情况下不包装成功的Web Api操作的结果,如果有需要,你可以添加WrapResult到操作或控制器上,但是默认包装异常。

你可以从(使用Configuration.Modules.AbpWebApi()...)改变这种默认行为。

 

动态Web Api层

ABP默认情况下包装动态Web Api层的方法结果,你可以通过在你的应用服务接口上使用WrapResult和DontWrapResult特性来改这种行为。

 

Asp.net Core 控制器

ABP自动包装JsonResult、ObjectResult和任何未实现IActionResult的结果,更多信息查看。

你可以从(使用Configuration.Modules.AbpAspNetCore()...)改变这种默认行为。

 

动态Web Api层

虽然ABP提供了一种简单使用AJAX的机制,但在一个真实世界的应用里,为每个AJAX调用写一个javascript函数还是很典型的,例如:

//Create a function to abstract AJAX callvar savePerson = function(person) {    return abp.ajax({        url: '/People/SavePerson',        data: JSON.stringify(person)    });};//Create a new personvar newPerson = {    name: 'Dougles Adams',    age: 42};//Save the personsavePerson(newPerson).done(function(data) {    abp.notify.success('created new person with id = ' + data.personId);});

为每个AJAX调用写一个函数,这是一个好的实践,但耗时且无趣, ABP可以自动地为和控制器生成这些类型的函数。

查阅动态Web Api层文档获取更多Web Api信息,查阅Asp.net Core文档获取有关集成信息。

 

kid1412附:

转载地址:http://flria.baihongyu.com/

你可能感兴趣的文章
xBIM 插入复制功能
查看>>
持续集成简介(转)
查看>>
一行代码让你的TableView动起来-iOS动画
查看>>
AI技术出海 - 阿里云GPU服务器助力旷视勇夺4项世界第一
查看>>
Spring Boot中初始化资源的几种方式
查看>>
通过测试发现的Exchange 2013 CU16存在的一个小bug
查看>>
将桌面文件映射至E盘
查看>>
走红日本 阿里云如何能够赢得海外荣耀
查看>>
入侵CIA和FBI的黑客:可能是一个15岁少年
查看>>
聚焦服务器行业,看美国独立服务器优势
查看>>
高中生开发 Chrome 插件,帮助色盲患者更为清晰的看到网上图片
查看>>
玩笑到现实,大数据涉足文学研究--用数据模型分析莎翁著作
查看>>
[Servlet&amp;JSP] HttpServletResponse的使用
查看>>
【java设计模式】之 单例(Singleton)模式
查看>>
Linux_自制系统服务启动脚本
查看>>
干货:解码OneData,传说中的阿里数据中台是如何练成的?
查看>>
gorename: easy refactoring tool for Golang[转]
查看>>
数据库进程间通信解决方案
查看>>
Guice框架-DI(依赖注入之作用域)
查看>>
海量数据计算应该如何选择数据库
查看>>