ASP.NET Core AutoWrapper 사용자 정의 응답 출력 구현

머리말
AutoWrapper 는 전역 이상 처리 프로그램 과 ASP.NET Core API 응답 을 간단하게 정의 할 수 있 는 포장 입 니 다.그 는 ASP.NET Core middleware 를 사용 하여 들 어 오 는 HTTP 요청 을 차단 하고 마지막 결 과 를 통 일 된 형식 으로 자동 으로 포장 합 니 다.업무 의 특정한 코드 요구 에 더 많은 관심 을 가지 고 포장 기 가 HTTP 응답 을 자동 으로 처리 하도록 하 는 것 이 목적 입 니 다.이것 은 API 를 구축 할 때 개발 시간 을 가속 화하 고 HTTP 응답 을 위해 통 일 된 표준 을 시험 해 볼 수 있다.
설치 하 다.
AutoWrapper.Core 는 NuGet 이나 CLI 를 통 해 다운로드 하고 설치 합 니 다.

PM> Install-Package AutoWrapper.Core 
Startup.cs Configure 방법 에 다음 과 같은 내용 을 등록 하지만 UseRouting 앞 에 두 어야 합 니 다.

app.UseApiResponseAndExceptionWrapper(); 

시작 속성 맵
기본적으로 AutoWrapper 는 요청 이 성공 할 때 다음 형식 을 출력 합 니 다.

{
  "message": "Request successful.",
  "isError": false,
  "result": [
   {
    "id": 7002,
    "firstName": "Vianne",
    "lastName": "Durano",
    "dateOfBirth": "2018-11-01T00:00:00"
   }
  ]
}
기본 속성 이름 방식 이 마음 에 들 지 않 는 다 면 AutoWrapper Property Map 속성 을 통 해 지정 해 야 할 모든 이름 을 매 핑 할 수 있 습 니 다.예 를 들 어 result 속성의 이름 을 data 로 변경 할 수 있 습 니 다.아래 와 같다

public class MapResponseObject 
{
  [AutoWrapperPropertyMap(Prop.Result)]
  public object Data { get; set; }
}
그리고 MapResponse Object 류 를 AutpWrapper middleware 에 전달 합 니 다.

app.UseApiResponseAndExceptionWrapper<MapResponseObject>(); 
맵 을 통 해 다시 요청 한 후,현재 영향 형식 은 다음 과 같 습 니 다.

{
  "message": "Request successful.",
  "isError": false,
  "data": {
    "id": 7002,
    "firstName": "Vianne",
    "lastName": "Durano",
    "dateOfBirth": "2018-11-01T00:00:00"
  }
}
result 속성 이 data 속성 으로 바 뀌 었 음 을 알 수 있 습 니 다.
기본적으로 AutoWrapper 에 이상 이 발생 하면 다음 응답 형식 을 토 합 니 다.

{
  "isError": true,
  "responseException": {
    "exceptionMessage": "Unhandled Exception occurred. Unable to process the request."
  }
}

또한 AutoWrapper Options 에 IsDebug 를 설정 하면 스 택 추적 정보 와 유사 한 정 보 를 생 성 합 니 다.

{
  "isError": true,
  "responseException": {
    "exceptionMessage": " Input string was not in a correct format.",
    "details": "  at System.Number.ThrowOverflowOrFormatException(ParsingStatus status, TypeCode type)\r
at System.Number.ParseInt32(ReadOnlySpan`1 value, NumberStyles styles, NumberFormatInfo info)\r
…" } }
일부 APIError 속성 이름 을 다른 이름 으로 변경 하려 면 다음 코드 에 맵 맵 ResponseObject 를 추가 하 십시오.

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"); 
현재 맵 의 출력 은 다음 과 같 습 니 다.

{
  "isError": true,
  "error": {
    "message": " Input string was not in a correct format.",
    "stackTrace": "  at System.Number.ThrowOverflowOrFormatException(ParsingStatus status, TypeCode type)\r
at System.Number.ParseInt32(ReadOnlySpan`1 value, NumberStyles styles, NumberFormatInfo info)\r
…" } }
APIError 는 현재 MapResponse Object 류 에서 정의 하 는 속성 에 따라 모델 의 기본 속성 을 변경 하 였 음 을 주의 하 십시오.
우 리 는 매 핑 속성 을 자 유 롭 게 선택 할 수 있 습 니 다.다음은 매 핑 속성 에 대응 하 는 목록 입 니 다.

[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 도 제공 합 니 다.자신의 이상 한 메 시 지 를 던 지 려 면 다음 작업 을 간단하게 수행 할 수 있 습 니 다.

throw new ApiException("Error blah", 400, "511", "http://blah.com/error/511"); 
기본 출력 형식 은 다음 과 같 습 니 다.

{
  "isError": true,
  "responseException": {
    "exceptionMessage": "Error blah",
    "referenceErrorCode": "511",
    "referenceDocumentLink": "http://blah.com/error/511"
  }
}
물론 오류 형식 을 사용자 정의 할 수 있 습 니 다.

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;
  }
}

그리고 우 리 는 다음 코드 를 통 해 우리 의 오 류 를 일 으 킬 수 있다.

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 응답 형식 사용
매 핑 이 우리 의 요 구 를 만족 시 키 지 못 한다 면.또한 API 응답 모델 에 다른 속성 을 추가 해 야 합 니 다.그러면 저 희 는 현재 자신의 형식 류 를 사용자 정의 할 수 있 습 니 다.UseCustomSchema 를 true 로 설정 하여 이 루어 집 니 다.코드 는 다음 과 같 습 니 다.

app.UseApiResponseAndExceptionWrapper(new AutoWrapperOptions { UseCustomSchema = true }); 
현재 주 API 에 응답 하 는 속성 SentDate 와 Pagination 대상 을 포함 하고 싶다 고 가정 하면 API 응답 모델 을 다음 과 같은 형식 으로 정의 하고 싶 을 수도 있 습 니 다.

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; }
}
다음 코드 세 션 을 통 해 테스트 결 과 를 진행 합 니 다.

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 응답 을 사용자 정의 하면 데 이 터 를 포맷 하 는 방식 을 완전히 제어 하고 기본 API 응답 의 일부 옵션 설정 을 잃 어 버 렸 음 을 주의해 야 합 니 다.그러나 저 희 는 ApiException()방법 으로 사용자 정의 오류 메 시 지 를 유발 할 수 있 습 니 다.
아래 와 같다

[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());
}

현재 모델 검증 을 진행 할 때 기본 응답 형식 을 얻 을 수 있 습 니 다.

{
  "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
여기 서 ASP.NET Core AutoWrapper 사용자 정의 응답 출력 실현 에 관 한 글 을 소개 합 니 다.더 많은 관련 ASP.NET Core AutoWrapper 응답 출력 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 도 많은 응원 부 탁 드 리 겠 습 니 다!

좋은 웹페이지 즐겨찾기