ABP Vnext Vue 的实现

{
// 返回格式类似这种
"success": false,
"message": "请求失败",
"data": null,
"code": 500
}
  • 定义返回类型
public class WrapResult<T>
{
private bool Success { get; set; }
private string Message { get; set; }
private T Data { get; set; }
private int Code { get; set; }
public WrapResult()
{
Success = true;
Message = "Success";
Data = default;
Code = 200;
}
public void SetSuccess(T data, string message = "Success", int code = 200)
{
Success = true;
Data = data;
Code = code;
}
public void SetFail(string message = "Fail", int code = 500)
{
Success = false;
Message = message;
Code = code;
}
}

实现思路

  • 定义 WrapResultAttribute
public class WrapResultAttribute : Attribute
{
}
  • 实现 IAsyncExceptionFilter(拦截异常,抛异常时指定返回格式)
public class ResultExceptionFilter : IFilterMetadata, IAsyncExceptionFilter, ITransientDependency
{
private ILogger<ResultExceptionFilter> Logger { get; set; }
private readonly IExceptionToErrorInfoConverter _errorInfoConverter;
private readonly IHttpExceptionStatusCodeFinder _statusCodeFinder;
private readonly IJsonSerializer _jsonSerializer;
private readonly AbpExceptionHandlingOptions _exceptionHandlingOptions;
public ResultExceptionFilter(
IExceptionToErrorInfoConverter errorInfoConverter,
IHttpExceptionStatusCodeFinder statusCodeFinder,
IJsonSerializer jsonSerializer,
IOptions<AbpExceptionHandlingOptions> exceptionHandlingOptions)
{
_errorInfoConverter = errorInfoConverter;
_statusCodeFinder = statusCodeFinder;
_jsonSerializer = jsonSerializer;
_exceptionHandlingOptions = exceptionHandlingOptions.Value;
Logger = NullLogger<ResultExceptionFilter>.Instance;
}
public async Task OnExceptionAsync(ExceptionContext context)
{
if (!ShouldHandleException(context))
{
return;
}
await HandleAndWrapException(context);
}
protected virtual bool ShouldHandleException(ExceptionContext context)
{
if (context.ActionDescriptor.AsControllerActionDescriptor().ControllerTypeInfo.GetCustomAttributes(typeof(WrapResultAttribute), true).Any())
{
return true;
}
if (context.ActionDescriptor.GetMethodInfo().GetCustomAttributes(typeof(WrapResultAttribute), true).Any())
{
return true;
} return false;
}
protected virtual async Task HandleAndWrapException(ExceptionContext context)
{
// 处理异常信息
context.HttpContext.Response.Headers.Add(AbpHttpConsts.AbpErrorFormat, "true");
var statusCode = (int)_statusCodeFinder.GetStatusCode(context.HttpContext, context.Exception);
context.HttpContext.Response.StatusCode = 200;
var remoteServiceErrorInfo = _errorInfoConverter.Convert(context.Exception, _exceptionHandlingOptions.SendExceptionsDetailsToClients);
remoteServiceErrorInfo.Code = context.HttpContext.TraceIdentifier;
remoteServiceErrorInfo.Message = SimplifyMessage(context.Exception);
// 返回格式统一
var result = new WrapResult<object>();
result.SetFail(remoteServiceErrorInfo.Message);
// HttpResponse
context.Result = new ObjectResult(result);
// 写日志
var logLevel = context.Exception.GetLogLevel();
var remoteServiceErrorInfoBuilder = new StringBuilder();
remoteServiceErrorInfoBuilder.AppendLine($"---------- {nameof(RemoteServiceErrorInfo)} ----------");
remoteServiceErrorInfoBuilder.AppendLine(_jsonSerializer.Serialize(remoteServiceErrorInfo, indented: true));
Logger.LogWithLevel(logLevel, remoteServiceErrorInfoBuilder.ToString());
Logger.LogException(context.Exception, logLevel);
await context.HttpContext
.RequestServices
.GetRequiredService<IExceptionNotifier>()
.NotifyAsync(
new ExceptionNotificationContext(context.Exception)
);
context.Exception = null; //Handled!
}
private string SimplifyMessage(Exception error)
{
string message = string.Empty;
switch (error)
{
case AbpAuthorizationException e:
return message = "Authenticate failure!";
case AbpValidationException e:
return message = "Request param validate failure!";
case EntityNotFoundException e:
return message = "not found the entity!";
case BusinessException e:
return message = $"{e.Message}";
case NotImplementedException e:
return message = "not implement!";
default:
return message = "server internal error!";
}
}
}

注册 Filter

 public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddMvc(options =>
{
options.Filters.Add(typeof(ResultExceptionFilter));
});
}

使用

  • 在 Controller 上或者 Action 上打上 WrapResultAttribute 特性
  • 例如
    [Route("Permissions")]
[WrapResult]
public class PermissionController : AbpProController,IRolePermissionAppService
{
private readonly IRolePermissionAppService _rolePermissionAppService; public PermissionController(IRolePermissionAppService rolePermissionAppService)
{
_rolePermissionAppService = rolePermissionAppService;
} [HttpPost("tree")]
[SwaggerOperation(summary: "获取角色权限", Tags = new[] { "Permissions" })]
[WrapResult] //控制器上打了 action上就不需要
public Task<PermissionOutput> GetPermissionAsync(GetPermissionInput input)
{
return _rolePermissionAppService.GetPermissionAsync(input);
} }

Abp Vnext 中如何统一接口返回值的更多相关文章

  1. .NetCore Web Api 利用ActionFilterAttribute统一接口返回值格式

    .Net Core 同 Asp.Net MVC一样有几种过滤器,这里不再赘述每个过滤器的执行顺序与作用. 在实际项目开发过程中,统一API返回值格式对前端或第三方调用将是非常必要的,在.NetCore ...

  2. 为什么阿里巴巴Java开发手册中强制要求接口返回值不允许使用枚举?

    在阅读<阿里巴巴Java开发手册>时,发现有一条关于二方库依赖中接口返回值不允许使用枚举类型的规约,具体内容如下: 在谈论为什么之前先来科普下什么是二方库,二方库也称作二方包,一般指公司内 ...

  3. nginx访问日志中添加接口返回值

    因为nginx作为web服务器时,会代理后端的一些接口,这时访问日志中只能记录访问接口的status码,也就是说,只能获得200.404 这些的值 那么如何获得接口返回的response值呢? 下面开 ...

  4. C#进阶系列——WebApi 接口返回值不困惑:返回值类型详解

    前言:已经有一个月没写点什么了,感觉心里空落落的.今天再来篇干货,想要学习Webapi的园友们速速动起来,跟着博主一起来学习吧.之前分享过一篇 C#进阶系列——WebApi接口传参不再困惑:传参详解  ...

  5. WebApi 接口返回值类型详解 ( 转 )

    使用过Webapi的园友应该都知道,Webapi的接口返回值主要有四种类型 void无返回值 IHttpActionResult HttpResponseMessage 自定义类型 此篇就围绕这四块分 ...

  6. WebApi接口返回值不困惑:返回值类型详解

    前言:已经有一个月没写点什么了,感觉心里空落落的.今天再来篇干货,想要学习Webapi的园友们速速动起来,跟着博主一起来学习吧.作为程序猿,我们都知道参数和返回值是编程领域不可分割的两大块,此前分享了 ...

  7. Asp.Net WebApi接口返回值IHttpActionResult

    WebApi是微软在VS2012 MVC4版本中绑定发行的,webapi2.0同mvc5发行的 webapi一共有以下接口返回值 1.void无返回值2.IHttpActionResult Json( ...

  8. WebApi 接口返回值不困惑:返回值类型详解。IHttpActionResult、void、HttpResponseMessage、自定义类型

    首先声明,我还没有这么强大的功底,只是感觉博主写的很好,就做了一个复制,请别因为这个鄙视我,博主网址:http://www.cnblogs.com/landeanfen/p/5501487.html ...

  9. (转)C# WebApi 接口返回值不困惑:返回值类型详解

    原文地址:http://www.cnblogs.com/landeanfen/p/5501487.html 正文 前言:已经有一个月没写点什么了,感觉心里空落落的.今天再来篇干货,想要学习Webapi ...

  10. [转]C#进阶系列——WebApi 接口返回值不困惑:返回值类型详解

    本文转自:http://www.cnblogs.com/landeanfen/p/5501487.html 阅读目录 一.void无返回值 二.IHttpActionResult 1.Json(T c ...

随机推荐

  1. draw.io 输入数学公式

    首先我们要把数学排版功能打开: 然后输入数学公式: AsciiMath 公式由 ` 包裹,如:`a2+b2 = c^2` LaTeX 公式由 $$ 包裹,如:$$\sqrt{3×-1}+(1+x)^2 ...

  2. sicp每日一题[1.42]

    Exercise 1.42 Let f and g be two one-argument functions. The composition f after g is defined to be ...

  3. 《SpringBoot事务》单机mybatis事务控制

    一.场景再现 我们同时操作两张表及以上,一张表操作成功后,第二张表操作失败,此时需要回滚上一次的操作. 或者两次操作都成功,但后续业务处理的时候异常,此时需要回滚前面的所有数据库操作. 二.代码 1 ...

  4. TypeScript 高级教程 – TypeScript 类型体操 (第三篇)

    前言 在 第一部 – 把 TypeScript 当强类型语言使用 和 第二部 – 把 TypeScript 当编程语言使用 后, 我们几乎已经把 TypeScript 的招数学完了. 第三部就要开始做 ...

  5. BOM – Window.matchMedia

    参考 Youtube – Detecting Screen Size and OS Dark Mode with matchMedia() - JavaScript Tutorial 介绍 CSS 有 ...

  6. SQL Server – Work with JSON

    前言 JSON 是一个很好的格式, array, object 就能表达一个表格了. 如果想保存一些结构格式, 又不想用表格这么大费周章的话, JSON 会是很好选择. 比如我用它来记入 Audit ...

  7. LeetCode题集-4 - 寻找两个有序数组的中位数,图文并茂,六种解法,万字讲解

    题目:给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2.请你找出并返回这两个正序数组的 中位数 . 算法的时间复杂度应该为 O(log (m+n)) . 作为目前遇到 ...

  8. MyBatis——解决SQL映射文件的警告提示

    解决SQL映射文件的警告提示 产生原因:idea 和数据库没有建立连接,不识别表信息 解决方式:在idea 中配置MySQL数据库连接   配置MySQL数据库连接:                  ...

  9. Flutter 因你更优秀 | 2021 第一季度开发者调研

    Flutter 终于在新的一年迎来了 2.0 版本,这是继 Dart 健全的空安全 Beta 版,以及 在测试方面取得重大进展 之后的一个全新的里程碑.在迈入这个新版本的当下,我们也已经准备好为大家带 ...

  10. 系统编程-进程-当文件操作遇上fork

    我的关联博文: 系统编程-进程-fork深度理解.vfork简介 系统编程-进程-先后fork或open一个文件的区别 test1:   lseek基本使用 #include <stdio.h& ...