日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

dotNET Core WebAPI 统一处理(返回值、参数验证、异常)

發布時間:2023/12/4 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 dotNET Core WebAPI 统一处理(返回值、参数验证、异常) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

現在 Web 開發比較流行前后端分離

現在 Web 開發比較流行前后端分離,我們的產品也是一樣,前端使用Vue,后端使用 dotNet Core WebAPI ,在寫 API 的過程中有很多地方需要統一處理

  • 文檔

  • 參數驗證

  • 返回值

  • 異常處理

本文就說說 API 的統一處理這些事。

環境

dotNet Core:2.1

文檔

Swagger 是一個 API 文檔生成框架,在非 Core 時代就一直在使用,現在前后端分離的模式下,API 文檔更是非常重要,讓前端開發人員和后端開發人員能更好的溝通和合作,前端開發人員在 Swagger 可以了解到接口的地址、入參、出參,還能模擬調用,非常方便。

安裝

在 VS For Mac 中創建 API 項目 DotNetCoreApiSample ,在依賴項中的 NuGet 上點擊右鍵,選擇添加包,如下圖:

搜索 Swashbuckle.AspNetCore,選中搜索結果的第一條,點擊「添加包」按鈕進行添加。

配置

Startup 類的 ConfigureServices 方法中添加

services.AddSwaggerGen(options?=> {options.SwaggerDoc("v1",?new?Swashbuckle.AspNetCore.Swagger.Info{Version?=?"v1",Title?=?"DotNet?Core?WebAPI文檔"});});

Startup 類的 Configure 方法中添加

app.UseSwagger(); app.UseSwaggerUI(c?=> {c.SwaggerEndpoint("/swagger/v1/swagger.json",?"DotNet?Core?WebAPI文檔"); });

運行效果

運行 WepAPI 項目,在瀏覽器中輸入 http://localhost:5000/swagger ,效果如下

參數驗證

此處所說的參數驗證指的是實體類型的參數驗證,通過在實體的屬性上添加特性的方式來實現。

簡單實現

創建名為 ValidationDemoController 的 API 類,代碼如下:

using?System; using?System.Collections.Generic; using?System.ComponentModel.DataAnnotations; using?System.Linq; using?System.Threading.Tasks; using?Microsoft.AspNetCore.Mvc;namespace?DotNetCoreApiSample.Controllers {[Route("api/[controller]")]public?class?ValidationDemoController?:?Controller{[HttpPost]public?IActionResult?AddUser([FromBody]User?user){string?errorMessage?=?string.Empty;if?(!ModelState.IsValid){foreach?(var?item?in?ModelState.Values){foreach?(var?error?in?item.Errors){errorMessage?+=?error.ErrorMessage?+?"|";}}}if(!string.IsNullOrEmpty(errorMessage)){return?BadRequest(errorMessage);}return?Ok();}}public?class?User{[Required(ErrorMessage?=?"用戶Code不能為空")]public?string?Code?{?get;?set;?}[Required(ErrorMessage?=?"用戶名稱不能為空")]public?string?Name?{?get;?set;?}[Required(ErrorMessage?=?"用戶年齡不能為空")][Range(1,?100,?ErrorMessage?=?"年齡必須介于1~100之間")]public?int?Age?{?get;?set;?}public?string?Address?{?get;?set;?}} }

  • 實體類屬性使用 Required 等特性需要引用命名空間System.ComponentModel.DataAnnotations

  • 除了上面的 Required 和 Range 標記,還有很多實用的標記,詳細參考:https://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations(v=vs.110).aspx

  • 上面的示例代碼將錯誤信息的收集寫在了接口方法中,這是一個很不好的做法,僅僅實現了功能,下面將通過過濾器的方式來進行重構,統一處理錯誤信息

重構

添加名為 ValidateModelAttribute 的過濾器類,繼承 ActionFilterAttribute ,代碼如下

namespace?DotNetCoreApiSample.Filters {public?class?ValidateModelAttribute?:?ActionFilterAttribute{public?override?void?OnActionExecuting(ActionExecutingContext?context){if?(!context.ModelState.IsValid){var?result?=?context.ModelState.Keys.SelectMany(key?=>?context.ModelState[key].Errors.Select(x?=>?new?ValidationError(key,?x.ErrorMessage))).ToList();context.Result?=?new?ObjectResult(result);}}}public?class?ValidationError{[JsonProperty(NullValueHandling?=?NullValueHandling.Ignore)]public?string?Field?{?get;?}public?string?Message?{?get;?}public?ValidationError(string?field,?string?message){Field?=?field?!=?string.Empty???field?:?null;Message?=?message;}} }

Startup 類的 ConfigureServices 方法中添加下面代碼:

services.AddMvc(options?=> {options.Filters.Add<ValidateModelAttribute>(); });

使用 Postman 調用結果如下

返回值

返回值的統一處理需要下面幾個步驟:

  • 創建統一返回結果的實體類,所有的接口方法都返回固定格式,方便前端統一處理

  • 創建過濾器,過濾器用來攔截請求,包裝結果,統一輸出

  • Startup 類中進行配置注冊

結果實體類

接口的返回值需要統一的格式,下面的屬性字段是我認為必須要有的

  • Result:返回的結果

  • Message:出現錯誤或需要提示時的提示文本內容

  • Code:調用成功、失敗或出錯時的編碼

  • ReturnStatus:用來判斷接口調用狀態的

創建返回結果的實體類 BaseResultModel

public?class?BaseResultModel {public?BaseResultModel(int??code?=?null,?string?message?=?null,object?result?=?null,?ReturnStatus?returnStatus?=?ReturnStatus.Success){this.Code?=?code;this.Result?=?result;this.Message?=?message;this.ReturnStatus?=?returnStatus;}public?int??Code?{?get;?set;?}public?string?Message?{?get;?set;?}public?object?Result?{?get;?set;?}public?ReturnStatus?ReturnStatus?{?get;?set;?} } public?enum?ReturnStatus {Success?=?1,Fail?=?0,ConfirmIsContinue?=?2,Error?=?3 }

過濾器類

創建名稱為 ApiResultFilterAttribute 的過濾器類,該類繼承 ActionFilterAttribute ,具體代碼如下

public?class?ApiResultFilterAttribute?:?ActionFilterAttribute {public?override?void?OnActionExecuting(ActionExecutingContext?context){base.OnActionExecuting(context);}public?override?void?OnResultExecuting(ResultExecutingContext?context){var?objectResult?=?context.Result?as?ObjectResult;context.Result?=?new?OkObjectResult(new?BaseResultModel(code:200,?result:?objectResult.Value));} }

在過濾器中將接口的返回值獲取后重新包裝到 BaseResultModel 模型類中進行返回。

Startup 配置

在 Startup 類的 ConfigureServices 方法中添加如下代碼

services.AddMvc(options?=> {options.Filters.Add<ValidateModelAttribute>();options.Filters.Add<ApiResultFilterAttribute>(); });

添加示例接口方法

[HttpGet] public?IActionResult?GetUserCode() {return?Ok("oec2003"); }

運行效果

使用 Postman 調用該接口方法,返回結果如下

繼續重構參數驗證

添加了返回值的過濾器類后,調用之前的參數驗證的接口,會發現返回結果如下

{"code":?200,"message":?null,"result":?[{"field":?"Age","message":?"年齡必須介于1~100之間"}],"returnStatus":?1 }

接口會調用兩次過濾器,先調用參數驗證的過濾器,再調用返回值的過濾器,導致驗證失敗的接口返回值狀態也是成功的,所以需要做進一步重構。

1、添加 ValidationFailedResultModel 類

public?class?ValidationFailedResultModel?:?BaseResultModel {public?ValidationFailedResultModel(ModelStateDictionary?modelState){Code?=?422;Message?=?"參數不合法";Result?=?modelState.Keys.SelectMany(key?=>?modelState[key].Errors.Select(x?=>?new?ValidationError(key,?x.ErrorMessage))).ToList();ReturnStatus?=?ReturnStatus.Fail;} }public?class?ValidationError {[JsonProperty(NullValueHandling?=?NullValueHandling.Ignore)]public?string?Field?{?get;?}public?string?Message?{?get;?}public?ValidationError(string?field,?string?message){Field?=?field?!=?string.Empty???field?:?null;Message?=?message;} }

將錯誤信息的收集移到了 ValidationFailedResultModel 類中,所以

2、修改 ValidateModelAttribute 過濾器,在修改代碼之前,先要添加名為 ValidationFailedResult 的類,該類繼承 ObjectResult ,用做參數驗證的結果收集。

public?class?ValidationFailedResult:?ObjectResult {public?ValidationFailedResult(ModelStateDictionary?modelState):?base(new?ValidationFailedResultModel(modelState)){StatusCode?=?StatusCodes.Status422UnprocessableEntity;} }

修改 ValidateModelAttribute 類

public?override?void?OnActionExecuting(ActionExecutingContext?context) {if?(!context.ModelState.IsValid){context.Result?=?new?ValidationFailedResult(context.ModelState);} }

3、修改 ApiResultFilterAttribute 過濾器,添加對 ValidationFailedResult 類型的判斷

public?override?void?OnResultExecuting(ResultExecutingContext?context) {if?(context.Result?is?ValidationFailedResult){var?objectResult?=?context.Result?as?ObjectResult;context.Result?=?objectResult;}else{var?objectResult?=?context.Result?as?ObjectResult;context.Result?=?new?OkObjectResult(new?BaseResultModel(code:?200,?result:?objectResult.Value));} }

4、調用參數驗證接口結果如下

異常處理

異常處理和參數驗證的方式基本相同,有以下幾個步驟

1、創建名為 CustomExceptionResultModel 的模型類

public?class?CustomExceptionResultModel:BaseResultModel {public?CustomExceptionResultModel(int??code,?Exception?exception){Code?=?code;Message?=?exception.InnerException?!=?null??exception.InnerException.Message?:exception.Message;Result?=?exception.Message;ReturnStatus?=?ReturnStatus.Error;} }

2、創建名為 CustomExceptionResult 的異常結果類

public?class?CustomExceptionResult:ObjectResult {public?CustomExceptionResult(int??code,?Exception?exception):?base(new?CustomExceptionResultModel(code,?exception)){StatusCode?=?code;} }

3、創建名為 CustomExceptionAttribute 的異常過濾器類,繼承自 IExceptionFilter

public?class?CustomExceptionAttribute?:?IExceptionFilter {public?void?OnException(ExceptionContext?context){HttpStatusCode?status?=?HttpStatusCode.InternalServerError;//處理各種異常context.ExceptionHandled?=?true;context.Result?=?new?CustomExceptionResult((int)status,?context.Exception);} }

4、Startup 配置

在 Startup 類的 ConfigureServices 方法中添加如下代碼

services.AddMvc(options?=> {options.Filters.Add<ValidateModelAttribute>();options.Filters.Add<ApiResultFilterAttribute>();options.Filters.Add<CustomExceptionAttribute>(); });

感興趣的朋友可以在 Github 上下載示例代碼進行調試。

總結

如果是從零開始搭建一個 WebAPI 項目,這些基礎處理是必不可少的,有了這些做保障才能專注于業務代碼的編寫。

本文只是拋磚引玉,同樣的思路我們還可以實現更多的功能,例如

  • 如果某些特殊接口需要直接返回值怎么辦?

  • 怎樣記錄耗時較長的接口?

  • 怎樣做接口的驗證?

點擊「閱讀原文」可訪問示例代碼。

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的dotNET Core WebAPI 统一处理(返回值、参数验证、异常)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。