Abp Vnext 中如何统一接口返回值
ABP Vnext Vue 的实现
在使用 abp 的过程中,如果提供给第三方接口要实现返回值统一需要怎么做?
{
// 返回格式类似这种
"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 中如何统一接口返回值的更多相关文章
- .NetCore Web Api 利用ActionFilterAttribute统一接口返回值格式
.Net Core 同 Asp.Net MVC一样有几种过滤器,这里不再赘述每个过滤器的执行顺序与作用. 在实际项目开发过程中,统一API返回值格式对前端或第三方调用将是非常必要的,在.NetCore ...
- 为什么阿里巴巴Java开发手册中强制要求接口返回值不允许使用枚举?
在阅读<阿里巴巴Java开发手册>时,发现有一条关于二方库依赖中接口返回值不允许使用枚举类型的规约,具体内容如下: 在谈论为什么之前先来科普下什么是二方库,二方库也称作二方包,一般指公司内 ...
- nginx访问日志中添加接口返回值
因为nginx作为web服务器时,会代理后端的一些接口,这时访问日志中只能记录访问接口的status码,也就是说,只能获得200.404 这些的值 那么如何获得接口返回的response值呢? 下面开 ...
- C#进阶系列——WebApi 接口返回值不困惑:返回值类型详解
前言:已经有一个月没写点什么了,感觉心里空落落的.今天再来篇干货,想要学习Webapi的园友们速速动起来,跟着博主一起来学习吧.之前分享过一篇 C#进阶系列——WebApi接口传参不再困惑:传参详解 ...
- WebApi 接口返回值类型详解 ( 转 )
使用过Webapi的园友应该都知道,Webapi的接口返回值主要有四种类型 void无返回值 IHttpActionResult HttpResponseMessage 自定义类型 此篇就围绕这四块分 ...
- WebApi接口返回值不困惑:返回值类型详解
前言:已经有一个月没写点什么了,感觉心里空落落的.今天再来篇干货,想要学习Webapi的园友们速速动起来,跟着博主一起来学习吧.作为程序猿,我们都知道参数和返回值是编程领域不可分割的两大块,此前分享了 ...
- Asp.Net WebApi接口返回值IHttpActionResult
WebApi是微软在VS2012 MVC4版本中绑定发行的,webapi2.0同mvc5发行的 webapi一共有以下接口返回值 1.void无返回值2.IHttpActionResult Json( ...
- WebApi 接口返回值不困惑:返回值类型详解。IHttpActionResult、void、HttpResponseMessage、自定义类型
首先声明,我还没有这么强大的功底,只是感觉博主写的很好,就做了一个复制,请别因为这个鄙视我,博主网址:http://www.cnblogs.com/landeanfen/p/5501487.html ...
- (转)C# WebApi 接口返回值不困惑:返回值类型详解
原文地址:http://www.cnblogs.com/landeanfen/p/5501487.html 正文 前言:已经有一个月没写点什么了,感觉心里空落落的.今天再来篇干货,想要学习Webapi ...
- [转]C#进阶系列——WebApi 接口返回值不困惑:返回值类型详解
本文转自:http://www.cnblogs.com/landeanfen/p/5501487.html 阅读目录 一.void无返回值 二.IHttpActionResult 1.Json(T c ...
随机推荐
- draw.io 使用自定义字体
draw.io 是我最常用的作图工具.然而,draw.io 支持的字体很少,只支持少数英文字体.不过好在 draw.io 提供了自定义选项,我们可以填入自己想要使用的字体的名称,然后 draw.io ...
- devops-3:Jenkins增加静态节点
Jenkins管理静态节点 Jenkins搭建完成后一般只有一个master节点,此节点主要用于管理Jenkins配置,如果再在master节点上跑一系列的Job,未免有点太勉强,并且如果出现资源紧缺 ...
- JVM笔记六-堆区知识之对象生命周期和GC的关系
通过上一篇文章的学习,我们对JVM堆区有了初步的认识,接下来,我们继续展开讲解堆区. 对象生命周期和GC的关系. 我们已经知道了,堆区的新生区分成了三个部分:伊甸园区.幸存者0区.幸存者1区. 其中0 ...
- Postman Code Java-Unirest 代码的依赖
本来是Postman的Code直接使用的,结果根据这个名字 Unirest,搜出来了很多依赖,使用了排名第一的, https://search.maven.org/search?q=Unirest 结 ...
- 又一个Rust练手项目-wssh(SSH over Websocket Client)
原文地址https://blog.fanscore.cn/a/61/ 1. wssh 1.1 开发背景 公司内部的发布系统提供一个连接到k8s pod的web终端,可以在网页中连接到k8s pod内. ...
- svg之viewbox缩放
先看个示例 代码如下: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> & ...
- ES6之常用开发知识点:let 和 const 命令详解(二)
let命令 基本用法 { let a = 10; var b = 1; } a // ReferenceError: a is not defined. b // 1 根据上面结果显示,let声明的变 ...
- java 线程、进程及相关知识点 《笔记一》
一.线程.进程 线程,就是是进程的一个单位,程序最小执行单位. 进程,就是一个执行中的应用程序:由此可见,进程是由很多线程组成的: 线程生命周期,就是管杀也管埋的过程,生老病死: 线程的5个状态: 新 ...
- 关于AutoCAD反复弹窗Nonvalid Software Detected的解决办法
事件起因: 客户安装的 CAD 2020 频繁弹窗Nonvalid Software Detected,报错内容:YOUR ACCESS IS NOW BLOCKED 解决办法: 在文件资源管理器 ...
- k8s的容器的webssh实现
Vite2.x + Vue3.x + Xtermjs4 相关信息 编程语言:TypeScript 4.x + JavaScript 构建工具:Vite 2.x 前端框架:Vue 3.x 路由工具:Vu ...