HttpResponseMessage 대신 IHttpActionResult를 사용해야하는 이유는 무엇입니까?


326

나는 WebApi로 개발하고 있으며 WebApi2로 이동하여 Microsoft가 a IHttpActionResult를 반환하는 데 사용되는 것이 좋습니다 새 인터페이스를 도입 했습니다 HttpResponseMessage. 이 새로운 인터페이스의 장점에 대해 혼란스러워합니다. 주로을 만드는 약간 쉬운 방법을 제공하는 것 같습니다 HttpResponseMessage.

나는 이것이 "추상화를위한 추상"이라고 주장 할 것이다. 뭔가 빠졌습니까? 이 새로운 인터페이스를 사용하면 한 줄의 코드를 저장하는 것 외에도 실제로 얻을 수있는 이점은 무엇입니까?

기존 방식 (WebApi) :

public HttpResponseMessage Delete(int id)
{
    var status = _Repository.DeleteCustomer(id);
    if (status)
    {
        return new HttpResponseMessage(HttpStatusCode.OK);
    }
    else
    {
        throw new HttpResponseException(HttpStatusCode.NotFound);
    }
}

새로운 방법 (WebApi2) :

public IHttpActionResult Delete(int id)
{
    var status = _Repository.DeleteCustomer(id);
    if (status)
    {
        //return new HttpResponseMessage(HttpStatusCode.OK);
        return Ok();
    }
    else
    {
        //throw new HttpResponseException(HttpStatusCode.NotFound);
        return NotFound();
    }
}

방금 흥미로운 것을 발견했습니다. 이 결과를 다른 사람이 확인할 수 있는지 잘 모르겠습니다. 그러나 일부 호출을 수행하면 성능이 크게 향상되었습니다. * 예제를 사용하면 9545 msHttpResponseMessage 후에 응답을 얻었습니다 . *은 Using I은 동일한 응답 돌아왔다 294 밀리 . IHttpActionResult
chris lesage

@ chrislesage 9545ms는 거의 10 초입니다. 심지어 294ms조차 느립니다. 100ms 이상 걸리는 것이 있으면 다른 것이 작동합니다. 그 이야기에는 ete를 만나는 것보다 더 많은 것이 있습니다.
AaronLS

답변:


305

IHttpActionResult기존 코드 HttpResponseMessage가 미리 준비된 응답 중 하나에 맞지 않는 코드를 작성하므로 사용하지 않기로 결정할 수 있습니다 . 그러나 의 미리 준비된 답변 HttpResponseMessageIHttpActionResult사용하여 적응할 수 있습니다 ResponseMessage. 이것을 알아내는 데 시간이 걸렸습니다. 따라서 반드시 하나를 선택할 필요가 없다는 것을 게시하고 싶었습니다.

public IHttpActionResult SomeAction()
{
   IHttpActionResult response;
   //we want a 303 with the ability to set location
   HttpResponseMessage responseMsg = new HttpResponseMessage(HttpStatusCode.RedirectMethod);
   responseMsg.Headers.Location = new Uri("http://customLocation.blah");
   response = ResponseMessage(responseMsg);
   return response;
}

참고 ResponseMessage기본 클래스의 방법 ApiController컨트롤러가 상속해야한다고.


1
ResponseMessage가 이제 ResponseMessageResult라는 것을 알기 위해 잠시 시간을 보냈습니다. 아마도 최근에 이름이 바뀌 었습니까? 추신 : 당신은 또한 답변에 새로운 키워드를 놓친 제안에 대한 많은 감사합니다 :)
Ilya Chernomordik

10
@IlyaChernomordik ResponseMessageResponseMessageResult는 다른 두 가지입니다. ResponseMessage()A는 방법ApiController컨트롤러가 상속, 따라서 단지 메서드 호출입니다해야한다. 따라서 new키워드가 필요 하지 않습니다 . 당신은 아마도 상속받지 않았 ApiController거나 정적 메소드 안에 있습니다. ResponseMessageResult의 반환 유형입니다 ResponseMessage().
AaronLS

3
@IlyaChernomordik 내가 쓴 수 response = base.ResponseMessage(responseMsg)는 더 명확는 기본 클래스 ApiController하는 방법입니다 있는지 확인하는
AaronLS

고맙게도 ApiController에서 상속받지 않은 서비스가 있었기 때문에 찾기에 시간이 걸렸습니다.
Ilya Chernomordik

3
@pootzko 당신은 맞습니다. 저는 OP가 두 가지 접근 방식이 실제로는 그렇지 않을 때 "오래된 방식"대 "새로운 방식"으로 프레임을 지정하여 상호 배타적이라고 믿었 음을 암시하는 것처럼 보였습니다. Darrel의 대답은 IHttpActionResult 반환의 이점 중 일부를 설명하는 데 도움이되며 내 대답은 이전 HttpResponseMessage를 IHttpActionResult로 변환하여 두 세계를 모두 활용할 수있는 방법을 보여줍니다.
AaronLS

84

계속 사용할 수 있습니다 HttpResponseMessage. 그 능력은 사라지지 않을 것입니다. 나는 당신과 같은 방식을 느꼈고 추가 추상화가 필요하지 않다고 팀과 광범위하게 논쟁했습니다. 그것의 존재를 정당화하려고 노력하는 몇 가지 논쟁이 있었지만 그것이 가치가 있다고 나에게 확신시키는 것은 없었습니다.

그건 내가 브래드 윌슨 에서이 샘플을 볼 때까지 입니다. 체인화 할 수있는 방식으로 클래스 를 구성 하면을 생성하기위한 "액션 수준" 응답 파이프 라인 을 만들 수 있습니다 . 커버 아래에서 이것은 구현 방법 이지만 동작 필터를 읽을 수없는 이유 중 하나 인 동작 방법을 읽을 때 그 순서는 명확하지 않습니다.IHttpActionResultHttpResponseMessageActionFiltersActionFilters

그러나 IHttpActionResult액션 메소드에 명시 적으로 연결할 수 있는 것을 작성하면 모든 종류의 다양한 동작을 구성하여 응답을 생성 할 수 있습니다.


62

다음의 몇 가지 이점이 있습니다 IHttpActionResult이상 HttpResponseMessage에서 언급 한 마이크로 소프트 ASP.Net 문서는 :

  • 컨트롤러의 단위 테스트를 간소화합니다.
  • HTTP 응답을 작성하기위한 공통 로직을 별도의 클래스로 이동합니다.
  • 응답 구성에 대한 하위 레벨 세부 사항을 숨겨 컨트롤러 조치의 의도를보다 명확하게합니다.

그러나 다음은 IHttpActionResult언급 할 가치가있는 다른 장점입니다 .

  • 단일 책임 원칙 존중 : 조치 메소드가 HTTP 요청을 처리하는 책임을 갖도록하고 HTTP 응답 메시지 작성에 관여하지 않습니다.
  • System.Web.Http.Results에 이미 정의 된 유용한 구현 즉, Ok NotFound Exception Unauthorized BadRequest Conflict Redirect InvalidModelState( 전체 목록으로 연결 )
  • 기본적으로 비동기 및 대기 를 사용합니다 .
  • ExecuteAsync메소드 를 구현 하여 자신 만의 ActionResult를 쉽게 만들 수 있습니다 .
  • HttpResponseMessage를 IHttpActionResult로 변환 하는 ResponseMessageResult ResponseMessage(HttpResponseMessage response)데 사용할 수 있습니다 .

32
// this will return HttpResponseMessage as IHttpActionResult
return ResponseMessage(httpResponseMessage); 

18

이것은 내 개인적인 의견이며 웹 API 팀의 사람들은 아마도 더 잘 설명 할 수 있지만 여기에는 2c가 있습니다.

우선, 나는 그것이 서로의 문제가 아니라고 생각합니다. 당신은 모두 당신이 당신의 행동 방식에 수행 할 작업에 만의 진정한 힘을 이해하기 위해 따라 사용할 수 있습니다 IHttpActionResult당신은 아마의 그 편리 헬퍼 메소드 이외의 단계로해야합니다, ApiControllerOk, NotFound

기본적으로 클래스 IHttpActionResult는의 팩토리로 구현한다고 생각합니다 HttpResponseMessage. 그런 생각을 가지게되면, 그것은 돌려 주어야하는 물건과 그것을 생산하는 공장이됩니다. 일반적인 프로그래밍 의미에서, 어떤 경우에는 객체를 직접 만들 수 있으며, 어떤 경우에는 그렇게하기 위해 팩토리가 필요합니다. 여기도 마찬가지입니다.

복잡한 로직을 통해 구성해야하는 응답 (예 : 많은 응답 헤더 등)을 반환하려는 경우 모든 로직을 동작 결과 클래스로 추상화 IHttpActionResult하여 여러 동작 메서드에서 사용하여 응답을 반환 할 수 있습니다.

IHttpActionResult반환 형식 으로 사용 하는 또 다른 이점 은 ASP.NET 웹 API 작업 방법을 MVC와 유사하게 만든다는 것입니다. 미디어 포맷터에 걸리지 않고 작업 결과를 반환 할 수 있습니다.

물론 Darrel이 지적했듯이 API 파이프 라인에서 작업 결과를 연결하고 메시지 처리기 자체와 유사한 강력한 마이크로 파이프 라인을 만들 수 있습니다. 이것은 당신의 행동 방법의 복잡성에 따라 필요할 것입니다.

긴 이야기는 짧습니다 . IHttpActionResult대결 이 아닙니다 HttpResponseMessage. 기본적으로 응답을 작성하는 방법입니다. 직접 또는 공장을 통해 수행하십시오.


팩토리 정당화와 관련된 문제는 ResponseFactory.CreateOkResponse()HttpResponseMessage를 반환 하는 것과 같은 정적 메서드를 쉽게 만들 수 있으며 응답을 만들 때 비동기 항목을 처리 할 필요가 없다는 것입니다. 한 팀원은 헤더 값을 생성하기 위해 I / O를 수행해야하는 경우 비동기가 유용 할 수 있다는 사실을 언급했습니다. 그래도 얼마나 자주 발생하는지 잘 모르겠습니다.
Darrel Miller

팩토리 메소드 패턴이 필요한 이유를 말하는 것과 같습니다. 정적 메서드를 사용하여 객체를 만드는 것이 어떻습니까? 물론 가능합니다. 모든 객체 생성이 적절한 팩토리 패턴을 제공하지는 않습니다. 그러나 IMHO는 클래스 모델링 방법에 달려 있습니다. 여러 정적 메소드의 형태로 클래스에 포함 된 여러 유형의 응답을 작성하거나 인터페이스에 따라 다른 클래스를 갖는 로직을 원하십니까? 다시 말하지만, 좋고 나쁨은 없습니다. 모든 것이 다릅니다. 어쨌든, 내 요점은 그것이 다른 것이 아니라 나는 개인적으로 공장을 좋아한다는 것입니다. :)
Badri

6

: 웹 API는 기본적으로 개체의 4 종류 반환 void, HttpResponseMessage, IHttpActionResult, 등의 강력한 유형. 웹 API의 첫 번째 버전은 HttpResponseMessageHTTP 응답 메시지를 매우 간단하게 반환 합니다.

IHttpActionResult일종 인 WebAPI 2에 의해 소개되었습니다 HttpResponseMessage. ExecuteAsync()을 만드는 방법 이 포함되어 있습니다 HttpResponseMessage. 컨트롤러의 단위 테스트를 단순화합니다.

다른 반환 유형은 미디어 포맷터를 사용하여 웹 API에 의해 응답 본문에 직렬화 된 강력한 유형의 클래스입니다. 단점은 404와 같은 오류 코드를 직접 반환 할 수 없다는 것입니다 HttpResponseException. 오류를 던지기 만하면 됩니다.


3

오히려 IHttpActionResult에 대한 TaskExecuteAsync 인터페이스 함수를 구현하고 싶습니다. 다음과 같은 것 :

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        var response = _request.CreateResponse(HttpStatusCode.InternalServerError, _respContent);

        switch ((Int32)_respContent.Code)
        { 
            case 1:
            case 6:
            case 7:
                response = _request.CreateResponse(HttpStatusCode.InternalServerError, _respContent);
                break;
            case 2:
            case 3:
            case 4:
                response = _request.CreateResponse(HttpStatusCode.BadRequest, _respContent);
                break;
        } 

        return Task.FromResult(response);
    }

여기서 _request는 HttpRequest이고 _respContent는 페이로드입니다.


2

IHttpActionResultover 를 사용하면 다음과 같은 이점이 있습니다 HttpResponseMessage.

  1. 를 사용하여 IHttpActionResult상태 코드가 아닌 전송되는 데이터에만 집중합니다. 따라서 코드가 더 깨끗하고 유지 관리가 쉽습니다.
  2. 구현 된 컨트롤러 방법의 단위 테스트가 더 쉬울 것입니다.
  3. 용도 asyncawait기본적으로.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.