我們開發接口時,一般都會涉及到參數校驗、異常處理、封裝結果返回等處理。如果每個后端開發在參數校驗、異常處理等都是各寫各的,沒有統一處理的話,代碼就不優雅,也不容易維護。所以,我們需要統一校驗參數,統一異常處理、統一結果返回,讓代碼更加規范、可讀性更強、更容易維護。
統一參數校驗
比如我們需要入參為必填,只需要在實體類字段添加 ?[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);}}
}