• Abp Vnext 中如何统一接口返回值


    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);
            }
    
        }
    
  • 相关阅读:
    LitJson.JsonException: Can't assign value '2347089724' (type System.UInt32) to type System.Int64
    unity特效ParticleSystem在UI上缩放(自适应屏幕)
    unity特效ParticleSystem用到UI上
    数据结构-线性表
    数据结构-各种树的简单理解
    图解排序算法之堆排序
    图解排序算法之快速排序—三数取中法
    图解排序算法之归并排序
    排序算法
    CSS 选择器及优先级
  • 原文地址:https://www.cnblogs.com/WangJunZzz/p/15616098.html
Copyright © 2020-2023  润新知