ASP.NET Core AutoWrapper 自定義響應(yīng)輸出實現(xiàn)
前言
AutoWrapper是一個簡單可自定義全局異常處理程序和ASP.NET Core API響應(yīng)的包裝。他使用ASP.NET Core middleware攔截傳入的HTTP請求,并將最后的結(jié)果使用統(tǒng)一的格式來自動包裝起來.目的主要是讓我們更多的關(guān)注業(yè)務(wù)特定的代碼要求,并讓包裝器自動處理HTTP響應(yīng)。這可以在構(gòu)建API時加快開發(fā)時間,同時為HTTP響應(yīng)試試我們統(tǒng)一的標(biāo)準(zhǔn)。
安裝
AutoWrapper.Core從NuGet或通過CLI下載并安裝
PM> Install-Package AutoWrapper.Core
在Startup.cs Configure方法中注冊以下內(nèi)容,但是切記要放在UseRouting前
app.UseApiResponseAndExceptionWrapper();
啟動屬性映射
默認(rèn)情況下AutoWrapper將在成功請求成功時輸出以下格式:
{ "message": "Request successful.", "isError": false, "result": [ { "id": 7002, "firstName": "Vianne", "lastName": "Durano", "dateOfBirth": "2018-11-01T00:00:00" } ] }
如果說不喜歡默認(rèn)屬性命名方式,那么我們可以通過AutoWrapperPropertyMap屬性進行映射為我們需要指定的任何名稱。例如我么可以將result屬性的名稱更改為data。如下所示
public class MapResponseObject { [AutoWrapperPropertyMap(Prop.Result)] public object Data { get; set; } }
然后將MapResponseObject類傳遞給AutpWrapper middleware
app.UseApiResponseAndExceptionWrapper<MapResponseObject>();
通過映射重新請求后,現(xiàn)在影響格式如下所示
{ "message": "Request successful.", "isError": false, "data": { "id": 7002, "firstName": "Vianne", "lastName": "Durano", "dateOfBirth": "2018-11-01T00:00:00" } }
可以從中看出result屬性已經(jīng)更換為data屬性了
默認(rèn)情況下AutoWrapper發(fā)生異常時將吐出以下響應(yīng)格式
{ "isError": true, "responseException": { "exceptionMessage": "Unhandled Exception occurred. Unable to process the request." } }
而且如果在AutoWrapperOptions中設(shè)置了IsDebug,則將產(chǎn)生帶有堆棧跟蹤信息的類似信息
{ "isError": true, "responseException": { "exceptionMessage": " Input string was not in a correct format.", "details": " at System.Number.ThrowOverflowOrFormatException(ParsingStatus status, TypeCode type)\r\n at System.Number.ParseInt32(ReadOnlySpan`1 value, NumberStyles styles, NumberFormatInfo info)\r\n …" } }
如果想將某些APIError屬性名稱更改為其他名稱,只需要在以下代碼中添加以下映射MapResponseObject
public class MapResponseObject { [AutoWrapperPropertyMap(Prop.ResponseException)] public object Error { get; set; } [AutoWrapperPropertyMap(Prop.ResponseException_ExceptionMessage)] public string Message { get; set; } [AutoWrapperPropertyMap(Prop.ResponseException_Details)] public string StackTrace { get; set; } }
通過如下代碼來模擬錯誤
int num = Convert.ToInt32("10s");
現(xiàn)在映射后的輸出如下所示
{ "isError": true, "error": { "message": " Input string was not in a correct format.", "stackTrace": " at System.Number.ThrowOverflowOrFormatException(ParsingStatus status, TypeCode type)\r\n at System.Number.ParseInt32(ReadOnlySpan`1 value, NumberStyles styles, NumberFormatInfo info)\r\n …" } }
請注意APIError現(xiàn)在根據(jù)MapResponseObject類中定義的屬性更改了模型的默認(rèn)屬性。
我們可以自由的選擇映射任何屬性,下面是映射屬性相對應(yīng)的列表
[AutoWrapperPropertyMap(Prop.Version)] [AutoWrapperPropertyMap(Prop.StatusCode)] [AutoWrapperPropertyMap(Prop.Message)] [AutoWrapperPropertyMap(Prop.IsError)] [AutoWrapperPropertyMap(Prop.Result)] [AutoWrapperPropertyMap(Prop.ResponseException)] [AutoWrapperPropertyMap(Prop.ResponseException_ExceptionMessage)] [AutoWrapperPropertyMap(Prop.ResponseException_Details)] [AutoWrapperPropertyMap(Prop.ResponseException_ReferenceErrorCode)] [AutoWrapperPropertyMap(Prop.ResponseException_ReferenceDocumentLink)] [AutoWrapperPropertyMap(Prop.ResponseException_ValidationErrors)] [AutoWrapperPropertyMap(Prop.ResponseException_ValidationErrors_Field)] [AutoWrapperPropertyMap(Prop.ResponseException_ValidationErrors_Message)]
自定義錯誤架構(gòu)
AutoWrapper還提供了一個APIException可用于定義自己的異常的對象,如果想拋出自己的異常消息,則可以簡單地執(zhí)行以下操作
throw new ApiException("Error blah", 400, "511", "http://blah.com/error/511");
默認(rèn)輸出格式如下所示
{ "isError": true, "responseException": { "exceptionMessage": "Error blah", "referenceErrorCode": "511", "referenceDocumentLink": "http://blah.com/error/511" } }
當(dāng)然我們可以自定義錯誤格式
public class MapResponseObject { [AutoWrapperPropertyMap(Prop.ResponseException)] public object Error { get; set; } } public class Error { public string Message { get; set; } public string Code { get; set; } public InnerError InnerError { get; set; } public Error(string message, string code, InnerError inner) { this.Message = message; this.Code = code; this.InnerError = inner; } } public class InnerError { public string RequestId { get; set; } public string Date { get; set; } public InnerError(string reqId, string reqDate) { this.RequestId = reqId; this.Date = reqDate; } }
然后我們可以通過如下代碼進行引發(fā)我們錯誤
throw new ApiException( new Error("An error blah.", "InvalidRange", new InnerError("12345678", DateTime.Now.ToShortDateString()) ));
輸出格式如下所示
{ "isError": true, "error": { "message": "An error blah.", "code": "InvalidRange", "innerError": { "requestId": "12345678", "date": "10/16/2019" } } }
使用自定義API響應(yīng)格式
如果映射滿足不了我們的需求。并且我們需要向API響應(yīng)模型中添加其他屬性,那么我們現(xiàn)在可以自定義自己的格式類,通過設(shè)置UseCustomSchema為true來實現(xiàn),代碼如下所示
app.UseApiResponseAndExceptionWrapper(new AutoWrapperOptions { UseCustomSchema = true });
現(xiàn)在假設(shè)我們想在主API中響應(yīng)中包含一個屬性SentDate和Pagination對象,我們可能希望將API響應(yīng)模型定義為以下格式
public class MyCustomApiResponse { public int Code { get; set; } public string Message { get; set; } public object Payload { get; set; } public DateTime SentDate { get; set; } public Pagination Pagination { get; set; } public MyCustomApiResponse(DateTime sentDate, object payload = null, string message = "", int statusCode = 200, Pagination pagination = null) { this.Code = statusCode; this.Message = message == string.Empty ? "Success" : message; this.Payload = payload; this.SentDate = sentDate; this.Pagination = pagination; } public MyCustomApiResponse(DateTime sentDate, object payload = null, Pagination pagination = null) { this.Code = 200; this.Message = "Success"; this.Payload = payload; this.SentDate = sentDate; this.Pagination = pagination; } public MyCustomApiResponse(object payload) { this.Code = 200; this.Payload = payload; } } public class Pagination { public int TotalItemsCount { get; set; } public int PageSize { get; set; } public int CurrentPage { get; set; } public int TotalPages { get; set; } }
通過如下代碼片段進行測試結(jié)果
public async Task<MyCustomApiResponse> Get() { var data = await _personManager.GetAllAsync(); return new MyCustomApiResponse(DateTime.UtcNow, data, new Pagination { CurrentPage = 1, PageSize = 10, TotalItemsCount = 200, TotalPages = 20 }); }
運行后會得到如下影響格式
{ "code": 200, "message": "Success", "payload": [ { "id": 1, "firstName": "Vianne", "lastName": "Durano", "dateOfBirth": "2018-11-01T00:00:00" }, { "id": 2, "firstName": "Vynn", "lastName": "Durano", "dateOfBirth": "2018-11-01T00:00:00" }, { "id": 3, "firstName": "Mitch", "lastName": "Durano", "dateOfBirth": "2018-11-01T00:00:00" } ], "sentDate": "2019-10-17T02:26:32.5242353Z", "pagination": { "totalItemsCount": 200, "pageSize": 10, "currentPage": 1, "totalPages": 20 } }
但是從這里要注意一旦我們對API響應(yīng)進行自定義,那么就代表我們完全控制了要格式化數(shù)據(jù)的方式,同時丟失了默認(rèn)API響應(yīng)的某些選項配置。但是我們?nèi)匀豢梢岳肁piException()方法引發(fā)用戶定義的錯誤消息
如下所示
[Route("{id:long}")] [HttpPut] public async Task<MyCustomApiResponse> Put(long id, [FromBody] PersonDTO dto) { if (ModelState.IsValid) { try { var person = _mapper.Map<Person>(dto); person.ID = id; if (await _personManager.UpdateAsync(person)) return new MyCustomApiResponse(DateTime.UtcNow, true, "Update successful."); else throw new ApiException($"Record with id: {id} does not exist.", 400); } catch (Exception ex) { _logger.Log(LogLevel.Error, ex, "Error when trying to update with ID:{@ID}", id); throw; } } else throw new ApiException(ModelState.AllErrors()); }
現(xiàn)在當(dāng)進行模型驗證時,可以獲得默認(rèn)響應(yīng)格式
{ "isError": true, "responseException": { "exceptionMessage": "Request responded with validation error(s). Please correct the specified validation errors and try again.", "validationErrors": [ { "field": "FirstName", "message": "'First Name' must not be empty." } ] } }
Reference
https://github.com/proudmonkey/AutoWrapper
到此這篇關(guān)于ASP.NET Core AutoWrapper 自定義響應(yīng)輸出實現(xiàn)的文章就介紹到這了,更多相關(guān)ASP.NET Core AutoWrapper響應(yīng)輸出內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#調(diào)用動態(tài)unlha32.dll解壓Lha后綴的打包文件分享
這篇文章介紹了,C#調(diào)用動態(tài)unlha32.dll解壓Lha后綴的打包文件,有需要的朋友可以參考一下2013-09-09AspNetPager分頁控件源代碼(Version 4.2)
AspNetPager分頁控件源代碼(Version 4.2)...2007-04-04.NET 6.0 + WPF 使用 Prism 框架實現(xiàn)導(dǎo)航
Prism是一款專為XAML應(yīng)用程序設(shè)計的開源框架,主要面向WPF和Xamarin Forms等平臺,文章介紹了Prism的基本概念、安裝步驟和使用方法,是開發(fā)企業(yè)級應(yīng)用程序的首選框架,感興趣的朋友跟隨小編一起看看吧2024-09-09ASP.NET動態(tài)增加HTML元素的方法實例小結(jié)
這篇文章主要介紹了ASP.NET動態(tài)增加HTML元素的方法,結(jié)合實例形式總結(jié)分析了asp.net針對樣式、Meta、js等元素動態(tài)增加相關(guān)操作技巧,需要的朋友可以參考下2017-01-01asp.net實現(xiàn)在XmlTextWriter中寫入一個CDATA的方法
這篇文章主要介紹了asp.net實現(xiàn)在XmlTextWriter中寫入一個CDATA的方法,結(jié)合實例形式分析了XmlTextWriter寫入CDATA的步驟與相關(guān)實現(xiàn)技巧,需要的朋友可以參考下2016-04-04