.NET Core统一参数校验、异常处理、结果返回

我们开发接口时,一般都会涉及到参数校验、异常处理、封装结果返回等处理。如果每个后端开发在参数校验、异常处理等都是各写各的,没有统一处理的话,代码就不优雅,也不容易维护。所以,我们需要统一校验参数,统一异常处理、统一结果返回,让代码更加规范、可读性更强、更容易维护。

统一参数校验

比如我们需要入参为必填,只需要在实体类字段添加  [Required].

 /// <summary>    ///    /// </summary>    public class AdminInputDto    {        /// <summary>        /// 账号        /// </summary>        [Required]        public string UserName { get; set; }
        /// <summary>        /// 密码        /// </summary>        [Required]        public string Password { get; set; }    }

然后再OnActionExecuting 进行验证

  public override void OnActionExecuting(ActionExecutingContext context)        {            //模型验证            if (!context.ModelState.IsValid)            {                throw new CustomException(context.ModelState.Values.First(p => p.Errors.Count > 0).Errors[0].ErrorMessage, ReturnCode.E1000002);            }            base.OnActionExecuting(context);        }
统一结果返回

统一标准的返回格式。一般一个标准的响应报文对象

code :响应状态码
message :响应结果描述
data:返回的数据
 
定义一个统一的返回对象模板
   /// <summary>    /// Service的返回数据    /// </summary>    public class ReturnData : ReturnData<object>    {    }
    /// <summary>    /// Service的返回数据    /// </summary>    public class ReturnData<T>    {        /// <summary>        /// 返回码        /// </summary>        public ReturnCode Code { get; set; }
        /// <summary>        /// 消息        /// </summary>        public string Message { get; set; }
        /// <summary>        /// 结果数据        /// </summary>        public T Data { get; set; }
        /// <summary>        /// 判断处理是否成功        /// </summary>        public bool Success        {            get { return ReturnCode.E10000 == Code; }        }    }
在控制器返回的时候,进行返回包装
  /// <summary>        /// 处理正常返回的结果对象        /// </summary>        /// <param name="context"></param>        public override void OnActionExecuted(ActionExecutedContext context)        {            if (context.Result != null)            {                var serializerSettings = new JsonSerializerSettings                {                    DateTimeZoneHandling = DateTimeZoneHandling.Local,                    DateFormatString = "yyyy-MM-ddTHH:mm:ss.fffzz:00",                    //设置缩进                    Formatting = Formatting.Indented,                    //设置json格式为驼峰式                    ContractResolver = new CamelCasePropertyNamesContractResolver()                };
                var result = context.Result as ObjectResult;                JsonResult newresult;                if (context.Result is ObjectResult)                {                    newresult = new JsonResult(new ReturnData { Message = "操作成功!", Code = ReturnCode.E10000, Data = result.Value }, serializerSettings);                }                else if (context.Result is EmptyResult)                {                    newresult = new JsonResult(new ReturnData { Message = "操作成功!", Code = ReturnCode.E10000 }, serializerSettings);                }                else                {                    throw new Exception($"未经处理的Result类型:{ context.Result.GetType().Name}");                }                context.Result = newresult;            }            base.OnActionExecuted(context);        }
统一异常处理
遇到未处理的异常进行统一的封装
  /// <summary>    /// api异常统一处理过滤器    /// </summary>    public class ApiExceptionFilterAttribute : ExceptionFilterAttribute    {        public override void OnException(ExceptionContext context)        {            context.Result = BuildExceptionResult(context.Exception);            base.OnException(context);        }
        /// <summary>        /// 包装处理异常格式        /// </summary>        /// <param name="ex"></param>        /// <returns></returns>        private JsonResult BuildExceptionResult(Exception ex)        {            var returnData = new ReturnData();            var exresult = ex as CustomException;            var WriteLog = true;            if (exresult != null)            {                //异常为自定义的异常                returnData.Code = exresult.ErrorCode;                returnData.Message = exresult.Message;                WriteLog = exresult.WriteLog;            }            else            {                //异常为未知异常                returnData.Code = ReturnCode.E1000001;                returnData.Message = ex.Message;            }
            //TODO 日志
            var serializerSettings = new JsonSerializerSettings            {                DateTimeZoneHandling = DateTimeZoneHandling.Local,                DateFormatString = "yyyy-MM-ddTHH:mm:ss.fffzz:00",                //设置缩进                Formatting = Formatting.Indented,                //设置json格式为驼峰式                ContractResolver = new CamelCasePropertyNamesContractResolver()            };
            return new JsonResult(returnData, serializerSettings);        }    }}