我们开发接口时,一般都会涉及到参数校验、异常处理、封装结果返回等处理。如果每个后端开发在参数校验、异常处理等都是各写各的,没有统一处理的话,代码就不优雅,也不容易维护。所以,我们需要统一校验参数,统一异常处理、统一结果返回,让代码更加规范、可读性更强、更容易维护。
统一参数校验
比如我们需要入参为必填,只需要在实体类字段添加 [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);
}
统一标准的返回格式。一般一个标准的响应报文对象
/// <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);
}
}
}