為什么還要寫這類文章?因為我看過網上很多講解的都不夠全面,而本文結合實際工作講解了swaggerui文檔,統一響應格式,異常處理,權限驗證等常用模塊,並提供一套完善的案例源代碼,在實際工作中可直接參考使用。
一、先看看最終效果
這是最后生成的swagerui文檔,大家可以直接訪問這個地址體驗:
http://sapi.daimali.com/swagger/ui/index
(若無法訪問,請公眾號CodeL聯系)
git源碼地址:https://gitee.com/daimali/WebApiDemo (推薦直接看源碼)
文檔效果圖:

響應的內容:
注意看紅色部分,所有的響應內容都將自動封裝成如下格式:由code,msg,data三部分組成
{ "code": 200, "msg": "OK", "data": { "List": [ { "OrderId": 1001, "UserName": "綠巨人", "OrderDate": "2018-11-18T09:39:36.0404502+08:00" }, { "OrderId": 1002, "UserName": "鋼鐵俠", "OrderDate": "2018-11-17T09:39:36.0404502+08:00" } ], "total": 20 } }
實現以上API的整體思路是:
1. 使用SwaggerUI自動生成接口文檔、便於團隊協作,減少工作量
2. 通過ActionFilter實現權限控制與響應格式的統一封裝
3. 通過ExceptionFilter實現異常的統一處理
我覺得大部分人閱讀到這里就可以了,剩下的時間去看看源碼,需要用的時候邊用邊學就好了
二、接口文檔 - SwaggerUI注意點
1. swagger漢化,注意swagger_lang.js 屬性生成操作需要選擇"嵌入的資源"
2. 項目右鍵-屬性-生成:輸出項勾選XML文檔文件


三、統一響應格式說明
通過 ApiResultFilterAttribute 類實現響應參數的統一封裝:ApiResultFilterAttribute繼承自ActionFilterAttribute
這里封裝的響應格式由如下三部分組成: code:跟隨HttpCode,msg:返回的描述信息, data:接口返回的業務數據統一放在data中
{ "code": 200, "msg": "OK", "data": null }
/// <summary> /// 響應數據 /// </summary> /// <typeparam name="T">自定義響應的內容</typeparam> public class ResponseApi<T> { /// <summary> /// 錯誤代碼 /// </summary> public int code { get; set; } /// <summary> /// 錯誤信息 /// </summary> public string msg { get; set; } /// <summary> /// 響應數據 /// </summary> public T data { get; set; } }
通過actionfilter統一封裝:
public class ApiResultFilterAttribute : ActionFilterAttribute { /// <summary> /// 進入action之前做權限驗證 /// </summary> public override void OnActionExecuting(HttpActionContext actionContext) { var token = true; //權限驗證省略 if (token) { ResponseApi<object> result = new ResponseApi<object>(); // 取得由 API 返回的狀態代碼 result.code = (int)HttpStatusCode.Unauthorized; // 取得由 API 返回的資料 result.data = null; result.msg = "invalid ticket value"; HttpResponseMessage response = new HttpResponseMessage { Content = new StringContent(JsonConvert.SerializeObject(result), Encoding.GetEncoding("UTF-8"), "application/json") }; //結果轉為自定義消息格式 HttpResponseMessage httpResponseMessage = response; // 重新封裝回傳格式 actionContext.Response = httpResponseMessage; } } /// <summary> /// 統一響應格式 /// </summary> public override void OnActionExecuted(HttpActionExecutedContext filterContext) { base.OnActionExecuted(filterContext); if (filterContext.ActionContext.Response != null) { ResponseApi<object> result = new ResponseApi<object>(); // 取得由 API 返回的狀態代碼 result.code = (int)filterContext.ActionContext.Response.StatusCode; // 取得由 API 返回的資料 result.data = filterContext.ActionContext.Response.Content.ReadAsAsync<object>().Result; HttpResponseMessage response = new HttpResponseMessage { Content = new StringContent(JsonConvert.SerializeObject(result), Encoding.GetEncoding("UTF-8"), "application/json") }; //結果轉為自定義消息格式 HttpResponseMessage httpResponseMessage = response; // 重新封裝回傳格式 filterContext.Response = httpResponseMessage; } } }
四、自定義異常信息
針對於所有的異常信息,接口也會返回對應的code,msg,data的格式:
通過CustomException和CustomExceptionFilterAttribute實現:
public class CustomExceptionFilterAttribute : ExceptionFilterAttribute { /// <summary> /// 統一對調用異常信息進行處理,返回自定義的異常信息 /// </summary> /// <param name="context">HTTP上下文對象</param> public override void OnException(HttpActionExecutedContext context) { //自定義異常的處理 if (context.Exception is CustomException) { var exception = (CustomException)context.Exception; ResponseApi<object> result = new ResponseApi<object>() { code = exception.GetErrorCode(), msg = exception.Message }; throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.OK) { //封裝處理異常信息,返回指定JSON對象 Content = new StringContent(JsonConvert.SerializeObject(result), Encoding.GetEncoding("UTF-8"), "application/json"), ReasonPhrase = "InternalServerErrorException", }); } else { ResponseApi<object> result = new ResponseApi<object>() { code = -1, msg = context.Exception.Message }; throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError) { //封裝處理異常信息,返回指定JSON對象 Content = new StringContent(JsonConvert.SerializeObject(result)), ReasonPhrase = "InternalServerErrorException" }); } } }
看源碼
需要說的東西太多,直接看源碼更方便:
接口預覽地址:http://sapi.daimali.com/swagger/ui/index
(若無法訪問,請公眾號聯系)
git源碼地址:https://gitee.com/daimali/WebApiDemo
繼續看詳細步驟:
1. 新建空ASP.NET MVC空應用程序,選擇WebApi
2. Nuget引用Swashbuckle.Core (demo目前用的v5.6.0最新穩定版)
3. 將App_Start中的類復制到你的新項目中,然后更改命名空間為你自己項目
4. 按需調整SwaggerConfig.cs 配置
5. 將Scripts文件復制到你的項目中,同時設置 swagger_lang.js 文件 屬性- 生成操作為"嵌入的資源",按需調整 swagger_lang.js文件內容
6. 注意你的WebApiConfig中需要添加 ApiResultFilterAttribute 和 CustomExceptionFilterAttribute
7. 項目右鍵-屬性-生成:輸出項勾選XML文檔文件
此時,你新建的webapi控制器已經支持swagger,並且會統一封裝成code,msg,data的格式了
修正:
1. HttpGet 請求接收參數時需要加 [FromUri]
2. token驗證不應該放在OnActionExecuted中,應該在接口執行之前,比如:AuthorizeAttribute中,或者 ActionFilterAttribute里面的OnActionExecuting方法(源碼已調整為OnActionExecuting )
評論區已知問題(待解決,后續將持續更新Demo,感興趣的同學多多關注):
1. 解決swagger 文件上傳問題
相關資源獲取或其他疑問可在公眾號CodeL留言。
