ASP.NET WebApi專案框架搭建(五):異常處理
阿新 • • 發佈:2020-04-23
一、前言
目的和原則
1、程式任何地方都不能catch掉異常,如果要catch也請重新throw異常或是將異常記錄到日誌裡。避免異常被“吃掉“,導致無法排查程式的bug。
2、webapi介面的”請求成功“和”請求失敗“以一定的標準規範提供給外部
3、如果為已知異常(即我們程式碼裡寫的throw異常)可簡單的記錄到日誌,但如果是未知異常(我們不知道是哪裡丟擲的異常,往往也是程式的bug)則記錄到特殊的日誌檔案裡,如上篇的log/error目錄下。
二、新建公共方法類庫
1.新建一個類庫用來儲存公共方法以供專案或者其他庫呼叫。
2.安裝Newtonsoft
3.新建Utils類,寫一個返回Json的類
public class Utils { public static HttpResponseMessage toJson(dynamic code,object result) { var response = Newtonsoft.Json.JsonConvert.SerializeObject(result); HttpResponseMessage res = new HttpResponseMessage(code); res.Content= new StringContent(response,Encoding.UTF8,"application/json"); return res; } }
4.系統的HttpStatusCode列舉可能不能滿足我們的需求,所以新建列舉類HttpCode,定義我們的返回碼:
public enum HttpCode { /// <summary> /// 成功 /// </summary> SUCCESS = 200,/// <summary> /// 失敗/// </summary> ERROR = 500,/// <summary> /// 引數錯誤 /// </summary> ERROR_PARAM = 600,/// <summary> /// 資料庫異常 /// </summary> DB_ERROR= 600,}
4.引用公共類庫
二、定義異常
1.新建Exceptions資料夾,新建KnownException類,繼承Exception,這個類主要是丟擲已知的異常資訊
public class KnownException : Exception { public HttpCode code; public string msg; public KnownException(HttpCode code,string msg) { this.code = code; this.msg = msg; } }
2.專案Models資料夾下建立一個Result類,用來定義訊息返回格式,對於null
添加註解[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
資料可以選擇忽略,不返回給客戶端
public class Result { /// <summary> /// 碼值 /// </summary> [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public HttpCode code; /// <summary> /// 資訊 /// </summary> [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public string msg; /// <summary> /// 具體的資料 /// </summary> [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public object data; public Result() { } public Result(HttpCode code,string msg,object data) { this.code = code; this.msg = msg; this.data = data; } }
3.Exceptions資料夾下新建WebApiExceptionFilterAttribute.cs,繼承ExceptionFilterAttribute,重寫OnException方法
/// <summary> /// 異常處理 /// </summary> public class WebApiExceptionFilterAttribute : ExceptionFilterAttribute { public override void OnException(HttpActionExecutedContext actionExecutedContext) { var exception = actionExecutedContext.Exception;//獲取產生的異常物件 var exceptionMessage = exception.Message; var logMessage = $@"controller.action={actionExecutedContext.ActionContext.ControllerContext.ControllerDescriptor.ControllerName}.{actionExecutedContext.ActionContext.ActionDescriptor.ActionName}:exception=" + exception.Message;//異常內容 ILog log = LogManager.GetLogger(actionExecutedContext.ActionContext.ControllerContext.Controller.GetType()); Result result = new Result(); if (exception is KnownException)//如果是已知異常 { log.Debug(logMessage); var ex = (KnownException)actionExecutedContext.Exception; result.code = ex.code; result.msg = ex.msg; } else//如果是未知異常 { log.Error(logMessage,exception); result.code = HttpCode.ERROR; result.msg = "內部錯誤"; result.data = exceptionMessage; } actionExecutedContext.ActionContext.Response = Utils.toJson(HttpStatusCode.BadRequest,result); } }
4.將異常過濾器加到webapiconfig.cs裡
config.Filters.Add(new WebApiExceptionFilterAttribute());
5.控制器新建一個請求,分別模擬丟擲已知異常和未知異常:
[Route("know")] [HttpGet] public IHttpActionResult Know() { throw new KnownException(HttpCode.DB_ERROR,"資料庫異常了"); } [HttpGet] [Route("unknow")] public IHttpActionResult UnKnow() { throw new System.IO.IOException(); }
6.測試結果:
7.異常結果也輸出到了日誌: