ASP.NET Core AutoWrapper 自定义响应输出实现
前言
AutoWrapper是一个简单可自定义全局异常处理程序和ASP.NETCoreAPI响应的包装。他使用ASP.NETCoremiddleware拦截传入的HTTP请求,并将最后的结果使用统一的格式来自动包装起来.目的主要是让我们更多的关注业务特定的代码要求,并让包装器自动处理HTTP响应。这可以在构建API时加快开发时间,同时为HTTP响应试试我们统一的标准。
安装
AutoWrapper.Core从NuGet或通过CLI下载并安装
PM>Install-PackageAutoWrapper.Core
在Startup.csConfigure方法中注册以下内容,但是切记要放在UseRouting前
app.UseApiResponseAndExceptionWrapper();
启动属性映射
默认情况下AutoWrapper将在成功请求成功时输出以下格式:
{
"message":"Requestsuccessful.",
"isError":false,
"result":[
{
"id":7002,
"firstName":"Vianne",
"lastName":"Durano",
"dateOfBirth":"2018-11-01T00:00:00"
}
]
}
如果说不喜欢默认属性命名方式,那么我们可以通过AutoWrapperPropertyMap属性进行映射为我们需要指定的任何名称。例如我么可以将result属性的名称更改为data。如下所示
publicclassMapResponseObject
{
[AutoWrapperPropertyMap(Prop.Result)]
publicobjectData{get;set;}
}
然后将MapResponseObject类传递给AutpWrappermiddleware
app.UseApiResponseAndExceptionWrapper();
通过映射重新请求后,现在影响格式如下所示
{
"message":"Requestsuccessful.",
"isError":false,
"data":{
"id":7002,
"firstName":"Vianne",
"lastName":"Durano",
"dateOfBirth":"2018-11-01T00:00:00"
}
}
可以从中看出result属性已经更换为data属性了
默认情况下AutoWrapper发生异常时将吐出以下响应格式
{
"isError":true,
"responseException":{
"exceptionMessage":"UnhandledExceptionoccurred.Unabletoprocesstherequest."
}
}
而且如果在AutoWrapperOptions中设置了IsDebug,则将产生带有堆栈跟踪信息的类似信息
{
"isError":true,
"responseException":{
"exceptionMessage":"Inputstringwasnotinacorrectformat.",
"details":"atSystem.Number.ThrowOverflowOrFormatException(ParsingStatusstatus,TypeCodetype)\r\natSystem.Number.ParseInt32(ReadOnlySpan`1value,NumberStylesstyles,NumberFormatInfoinfo)\r\n…"
}
}
如果想将某些APIError属性名称更改为其他名称,只需要在以下代码中添加以下映射MapResponseObject
publicclassMapResponseObject
{
[AutoWrapperPropertyMap(Prop.ResponseException)]
publicobjectError{get;set;}
[AutoWrapperPropertyMap(Prop.ResponseException_ExceptionMessage)]
publicstringMessage{get;set;}
[AutoWrapperPropertyMap(Prop.ResponseException_Details)]
publicstringStackTrace{get;set;}
}
通过如下代码来模拟错误
intnum=Convert.ToInt32("10s");
现在映射后的输出如下所示
{
"isError":true,
"error":{
"message":"Inputstringwasnotinacorrectformat.",
"stackTrace":"atSystem.Number.ThrowOverflowOrFormatException(ParsingStatusstatus,TypeCodetype)\r\natSystem.Number.ParseInt32(ReadOnlySpan`1value,NumberStylesstyles,NumberFormatInfoinfo)\r\n…"
}
}
请注意APIError现在根据MapResponseObject类中定义的属性更改了模型的默认属性。
我们可以自由的选择映射任何属性,下面是映射属性相对应的列表
[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)]
自定义错误架构
AutoWrapper还提供了一个APIException可用于定义自己的异常的对象,如果想抛出自己的异常消息,则可以简单地执行以下操作
thrownewApiException("Errorblah",400,"511","http://blah.com/error/511");
默认输出格式如下所示
{
"isError":true,
"responseException":{
"exceptionMessage":"Errorblah",
"referenceErrorCode":"511",
"referenceDocumentLink":"http://blah.com/error/511"
}
}
当然我们可以自定义错误格式
publicclassMapResponseObject
{
[AutoWrapperPropertyMap(Prop.ResponseException)]
publicobjectError{get;set;}
}
publicclassError
{
publicstringMessage{get;set;}
publicstringCode{get;set;}
publicInnerErrorInnerError{get;set;}
publicError(stringmessage,stringcode,InnerErrorinner)
{
this.Message=message;
this.Code=code;
this.InnerError=inner;
}
}
publicclassInnerError
{
publicstringRequestId{get;set;}
publicstringDate{get;set;}
publicInnerError(stringreqId,stringreqDate)
{
this.RequestId=reqId;
this.Date=reqDate;
}
}
然后我们可以通过如下代码进行引发我们错误
thrownewApiException(
newError("Anerrorblah.","InvalidRange",
newInnerError("12345678",DateTime.Now.ToShortDateString())
));
输出格式如下所示
{
"isError":true,
"error":{
"message":"Anerrorblah.",
"code":"InvalidRange",
"innerError":{
"requestId":"12345678",
"date":"10/16/2019"
}
}
}
使用自定义API响应格式
如果映射满足不了我们的需求。并且我们需要向API响应模型中添加其他属性,那么我们现在可以自定义自己的格式类,通过设置UseCustomSchema为true来实现,代码如下所示
app.UseApiResponseAndExceptionWrapper(newAutoWrapperOptions{UseCustomSchema=true});
现在假设我们想在主API中响应中包含一个属性SentDate和Pagination对象,我们可能希望将API响应模型定义为以下格式
publicclassMyCustomApiResponse
{
publicintCode{get;set;}
publicstringMessage{get;set;}
publicobjectPayload{get;set;}
publicDateTimeSentDate{get;set;}
publicPaginationPagination{get;set;}
publicMyCustomApiResponse(DateTimesentDate,objectpayload=null,stringmessage="",intstatusCode=200,Paginationpagination=null)
{
this.Code=statusCode;
this.Message=message==string.Empty?"Success":message;
this.Payload=payload;
this.SentDate=sentDate;
this.Pagination=pagination;
}
publicMyCustomApiResponse(DateTimesentDate,objectpayload=null,Paginationpagination=null)
{
this.Code=200;
this.Message="Success";
this.Payload=payload;
this.SentDate=sentDate;
this.Pagination=pagination;
}
publicMyCustomApiResponse(objectpayload)
{
this.Code=200;
this.Payload=payload;
}
}
publicclassPagination
{
publicintTotalItemsCount{get;set;}
publicintPageSize{get;set;}
publicintCurrentPage{get;set;}
publicintTotalPages{get;set;}
}
通过如下代码片段进行测试结果
publicasyncTaskGet() { vardata=await_personManager.GetAllAsync(); returnnewMyCustomApiResponse(DateTime.UtcNow,data, newPagination { 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响应进行自定义,那么就代表我们完全控制了要格式化数据的方式,同时丢失了默认API响应的某些选项配置。但是我们仍然可以利用ApiException()方法引发用户定义的错误消息
如下所示
[Route("{id:long}")]
[HttpPut]
publicasyncTaskPut(longid,[FromBody]PersonDTOdto)
{
if(ModelState.IsValid)
{
try
{
varperson=_mapper.Map(dto);
person.ID=id;
if(await_personManager.UpdateAsync(person))
returnnewMyCustomApiResponse(DateTime.UtcNow,true,"Updatesuccessful.");
else
thrownewApiException($"Recordwithid:{id}doesnotexist.",400);
}
catch(Exceptionex)
{
_logger.Log(LogLevel.Error,ex,"ErrorwhentryingtoupdatewithID:{@ID}",id);
throw;
}
}
else
thrownewApiException(ModelState.AllErrors());
}
现在当进行模型验证时,可以获得默认响应格式
{
"isError":true,
"responseException":{
"exceptionMessage":"Requestrespondedwithvalidationerror(s).Pleasecorrectthespecifiedvalidationerrorsandtryagain.",
"validationErrors":[
{
"field":"FirstName",
"message":"'FirstName'mustnotbeempty."
}
]
}
}
Reference
https://github.com/proudmonkey/AutoWrapper
到此这篇关于ASP.NETCoreAutoWrapper自定义响应输出实现的文章就介绍到这了,更多相关ASP.NETCoreAutoWrapper响应输出内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。