webapi框架搭建-webapi異常處理


webapi框架搭建系列博客

前言

  上一篇我們已經完成了項目的日志管理,在項目開發中日志會經常記錄程序中的異常,供后續問題排查使用。本篇講如何在webapi里加入異常處理機制。

目的和原則

  1、程序任何地方都不能catch掉異常,如果要catch也請重新throw異常或是將異常記錄到日志里。避免異常被“吃掉“,導致無法排查程序的bug。

  2、webapi接口的”請求成功“和”請求失敗“以一定的標准規范提供給外部

    我的規范為:

    所有的成功請求返回200(response的status為200),返回的結果以json封裝

    所有的失敗請求返回非200,錯誤以json返回,錯誤的內容為Message的值,如{"Message":"這里是異常的內容描述"}

  3、如果為已知異常(即我們代碼里寫的throw異常)可簡單的記錄到日志,但如果是未知異常(我們不知道是哪里拋出的異常,往往也是程序的bug)則記錄到特殊的日志文件里,如上篇的log/error目錄下。

參考

微軟webapi異常處理:https://docs.microsoft.com/zh-cn/aspnet/web-api/overview/error-handling/

 

步驟如下

自定義異常類

  此異常類即是”已知“異常,約定程序里我們自己拋出的異常都用此類,Message屬性記錄異常的描述信息

using System;
using System.Runtime.Serialization;

namespace webapi.Exceptions
{
    public class KnownException : Exception
    {
        public KnownException():base()
        {
        }

        public KnownException(string message) : base(message)
        {
        }

        public KnownException(string message, Exception innerException) : base(message, innerException)
        {
        }

        protected KnownException(SerializationInfo info, StreamingContext context) : base(info, context)
        {
        }
    }
}

 

創建webapi異常過濾器

  創建WebApiExceptionFilterAttribute類,代碼如下

using System.Net;
using System.Net.Http;
using System.Web.Http.Filters;
using log4net;

namespace webapi.Exceptions
{
    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());
            if (exception is KnownException)
            {
                log.Debug(logMessage);
            }
            else
            {
                log.Error(logMessage, exception);
            }
            actionExecutedContext.Response = actionExecutedContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, exceptionMessage);
        }

    }
}

  在webapi里使用異常過濾最簡單的方法就是繼承自ExceptionFilterAttribute類,並重寫OnException方法並寫入自己的異常處理邏輯

將異常過濾器加到webapi里

修改之前的WebApiConfig.OwinWebApiConfiguration方法,代碼如下

/// <summary>
        /// 返回webapi的httpconfiguration配置
        /// 用於webapi應用於owin技術時使用
        /// </summary>
        /// <returns></returns>
        public static HttpConfiguration OwinWebApiConfiguration(HttpConfiguration config)
        {
            config.MapHttpAttributeRoutes();//開啟屬性路由
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
            config.Filters.Add(new WebApiExceptionFilterAttribute());
            return config;
        }

  增加的只是config.Filters.Add(new WebApiExceptionFilterAttribute());這一句

 

測試結果

創建用於測試的控制器,寫兩個接口分別模擬程序bug拋出的未知異常和自己拋出的已知異常

using System;
using System.Web.Http;
using webapi.Exceptions;

namespace webapi.example
{
    [RoutePrefix("api/exceptionTest")]
    public class ExceptionTestController : ApiController
    {
        /// <summary>
        /// 模擬程序bug拋出的異常
        /// </summary>
        /// <returns></returns>
        [Route("unknown"),HttpGet]
        public IHttpActionResult UnKnow()
        {
            throw new Exception("未知的異常");
        }
        /// <summary>
        /// 模擬主動拋出的業務異常
        /// </summary>
        /// <returns></returns>
        [Route("known"), HttpGet]
        public IHttpActionResult Know()
        {
            throw new KnownException("已知的異常");
        }
    }
}

  返問兩個接口會得到內容為{"Message":"xxx"},status為400的respose,和我們的約定規則一樣。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM