비 OK 응답에 대해 IHttpActionResult를 사용하여 컨텐츠 리턴


185

Web API 2 컨트롤러에서 돌아 오는 경우 다음과 같이 응답이 정상이면 (상태 200) 응답이 포함 된 콘텐츠를 반환 할 수 있습니다.

    public IHttpActionResult Get()
    {
        string myResult = ...
        return Ok(myResult);
    }

가능한 경우 여기에 기본 제공 결과 형식을 사용하고 싶습니다. https://msdn.microsoft.com/en-us/library/system.web.http.results(v=vs.118).aspx

내 질문은 다른 유형의 응답 (200이 아닌)에 대해 어떻게 메시지 (문자열)를 반환 할 수 있습니까? 예를 들어, 나는 이것을 할 수 있습니다 :

    public IHttpActionResult Get()
    {
       return InternalServerError();
    }

그러나 이것은 아닙니다 :

    public IHttpActionResult Get()
    {
       return InternalServerError("Message describing the error here");
    }

이상적으로는 IHttpActionResult 구현으로 메시지를 다시 보낼 수 있도록 이것을 일반화하고 싶습니다.

이 작업을 수행해야하며 자체 응답 메시지를 작성해야합니다.

    public IHttpActionResult Get()
    {
       HttpResponseMessage responseMessage = ...
       return ResponseMessage(responseMessage);
    }

아니면 더 좋은 방법이 있습니까?




@Milen, 감사합니다. 그런 식으로 작동 할 수 있습니다. 내가 싫어하는 부분은 사용할 수있는 기존 구현마다 다른 IHttpActionResult 구현을 만들어야한다는 것입니다.
mayabelle

@Ric, 아니오, 매개 변수는 예외입니다. 메시지를 문자열로 설정하고 싶습니다. 또한 코드가 내부 서버 오류 일 필요는없는보다 일반적인 경우를 다루지는 않습니다.
mayabelle

3
@ mayabelle : Shamil Yakupov의 대답을 보셨습니까? 수락 된 답변이 훨씬 간단하고 간결합니다.
Isaac Isaac

답변:


420

이것을 사용할 수 있습니다 :

return Content(HttpStatusCode.BadRequest, "Any object");

1
짧고 간단한 솔루션. 코드가 많을수록 더 많은 버그와 시간이 소요되는 유지 관리가 필요합니다.
Thomas.Benz

6
내가 이것을 시도 할 때, code(코드가 문자열 인) 의 반환 값은 return Content(HttpStatusCode.OK, code)"예기치 "\"value\""않은데 , 어떤 이유가 있습니까?"에 캡슐화되어 있습니다. 예를 들어 반환되는 값은 mvc5를 사용하고 있습니다
Deza

2
ApiController 클래스 외부에서이 작업을 수행해야하는 경우 다음을 사용할 수 있습니다. return new NegotiatedContentResult <T> (code, new T (...), controller)
Etherman

클래스 라이브러리에서 반환 할 수 있습니까? 무엇을 참조해야합니까?
툴킷

54

HttpRequestMessagesExtensions.CreateErrorResponse ( System.Net.Http네임 스페이스)를 다음과 같이 사용할 수 있습니다 .

public IHttpActionResult Get()
{
   return ResponseMessage(Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "Message describing the error here"));
}

웹 API의 컨텐츠 협상을 이용하려면 요청을 기반으로 응답을 작성하는 것이 좋습니다.


6
Request.CreateErrorResponse는 IHttpActionResult가 아닌 HttpResponseMessage를 반환합니다. 당신이 설명하는 것은 HttpResponseMessage를 만드는 좋은 습관이지만 내 질문을 다루지 않습니다. 어쨌든 고마워!
mayabelle

@mayabelle 당신은 IHttpActionResult 콘크리트를 만들고 다음과 같은 코드를 감쌀 수 있습니다 :
Quoc Nguyen

1
이것은 나를 위해 일했지만 Request.CreateResponse를 사용하여 오류가 메시지 키 대신 문자열로 표시되도록했습니다.
화학자

오류가 발생하여 스 니펫이 실패했습니다. '요청'이 null이라고 말합니다. 나는 Request.CreateResponse @ user1620220 사용하는 것을 시도하고있다
시나 아그라 왈

@SheenaAgrawal이 코드는 HTTP 요청 컨텍스트에서만 실행될 수 있습니다. ApiController.Requestnull 인 경우 올바른 컨텍스트에 있지 않거나 WebAPI 아키텍처에서 무언가가 손상되었음을 의미합니다.
user1620220

35

나는 다음 해결책을 찾았다.

public class HttpActionResult : IHttpActionResult
{
    private readonly string _message;
    private readonly HttpStatusCode _statusCode;

    public HttpActionResult(HttpStatusCode statusCode, string message)
    {
        _statusCode = statusCode;
        _message = message;
    }

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        HttpResponseMessage response = new HttpResponseMessage(_statusCode)
        {
            Content = new StringContent(_message)
        };
        return Task.FromResult(response);
    }
}

... 다음과 같이 사용할 수 있습니다.

public IHttpActionResult Get()
{
   return new HttpActionResult(HttpStatusCode.InternalServerError, "error message"); // can use any HTTP status code
}

개선을위한 제안을 받고 있습니다. :)


1
Shamil Yakupov의 답변은 ApiController 클래스 내부에서만 가장 좋은 답변입니다. 외부에서 사용하려면 "return new NegotiatedContentResult <T> (code, new T (...), controller)"와 같이 다시 작성해야합니다. 컨트롤러 클래스. 이 경우, 위와 같은 해결책이 더 읽기 쉽습니다.
Etherman

16

당신은 또한 할 수 있습니다 :

return InternalServerError(new Exception("SOME CUSTOM MESSAGE"));

1
그렇습니다. 그러나 그 메시지를 다시받는 것은 고통입니다
userSteve

7

ResponseMessage를 반환하여 상태 코드가있는 것을 반환하는 데 관심이있는 사람 :

//CreateResponse(HttpStatusCode, T value)
return ResponseMessage(Request.CreateResponse(HttpStatusCode.XX, object));

7

ASP.NET Web API 2에서는 ResponseMessageResultResponseMessage 에서 아무 것도 랩핑 할 수 있습니다 .

public IHttpActionResult Get()
{
   HttpResponseMessage responseMessage = ...
   return new ResponseMessageResult(responseMessage);
}

경우에 따라 원하는 결과를 얻는 가장 간단한 방법 일 수도 있지만 일반적으로 System.Web.Http.Results 의 다양한 결과를 사용하는 것이 좋습니다 .


6

단순한:

return ResponseMessage(Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "Your message"));

System.Net.HttpSystem.Net 을 참조하십시오 .



2

C #에 정의되지 않은 HTTP 코드를 지원하는보다 자세한 예제입니다 HttpStatusCode.

public class MyController : ApiController
{
    public IHttpActionResult Get()
    {
        HttpStatusCode codeNotDefined = (HttpStatusCode)429;
        return Content(codeNotDefined, "message to be sent in response body");
    }
}

ContentApiController컨트롤러의 기본 추상 클래스에 정의 된 가상 메소드 입니다. 아래와 같이 선언을 참조하십시오.

protected internal virtual NegotiatedContentResult<T> Content<T>(HttpStatusCode statusCode, T value);

1

@mayabelle 당신은 IHttpActionResult 콘크리트를 만들고 다음과 같이 코드를 감쌀 수 있습니다 :

public class NotFoundPlainTextActionResult : IHttpActionResult
{
    public NotFoundPlainTextActionResult(HttpRequestMessage request, string message)
    {
        Request = request;
        Message = message;
    }

    public string Message { get; private set; }
    public HttpRequestMessage Request { get; private set; }

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        return Task.FromResult(ExecuteResult());
    }

    public HttpResponseMessage ExecuteResult()
    {
        var response = new HttpResponseMessage();

        if (!string.IsNullOrWhiteSpace(Message))
            //response.Content = new StringContent(Message);
            response = Request.CreateErrorResponse(HttpStatusCode.NotFound, new Exception(Message));

        response.RequestMessage = Request;
        return response;
    }
}

0

나는 같은 문제가 있었다. API 컨트롤러에 대한 사용자 정의 결과를 만들고 싶습니다. return Ok("some text");

그런 다음이 작업을 수행했습니다 : 1) 단일 톤으로 사용자 정의 결과 유형 생성

public sealed class EmptyResult : IHttpActionResult
{
    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        return Task.FromResult(new HttpResponseMessage(System.Net.HttpStatusCode.NoContent) { Content = new StringContent("Empty result") });
    }
}

2) 새로운 방법으로 사용자 정의 컨트롤러를 만듭니다.

public class CustomApiController : ApiController
{
    public IHttpActionResult EmptyResult()
    {
        return new EmptyResult();
    }
}

그런 다음 컨트롤러에서 다음과 같이 호출 할 수 있습니다.

public IHttpActionResult SomeMethod()
    {
       return EmptyResult();
    }

0

이 답변은 문자열 대신 실제 객체가있는 Shamil Yakupov 답변을 기반으로합니다.

using System.Dynamic;

dynamic response = new ExpandoObject();
response.message = "Email address already exist";

return Content<object>(HttpStatusCode.BadRequest, response);

1
Content <T>는 매우 유용합니다
LastTribunal

0

예외적으로 나는 보통

 catch (Exception ex)
        {
            return InternalServerError(new ApplicationException("Something went wrong in this request. internal exception: " + ex.Message));
        }

0

위의 것들이 정말 도움이됩니다.

웹 서비스를 작성하는 동안 서비스의 경우 소비자는 크게 감사하겠습니다. 출력의 균일 성을 유지하려고했습니다. 또한 당신은 말이나 실제 오류 메시지를 줄 수 있습니다. 웹 서비스 소비자는 IsSuccess 만 확인하거나 문제가 있는지 확인하지 않고 상황에 따라 작동 할 수 있습니다.

  public class Response
    {
        /// <summary>
        /// Gets or sets a value indicating whether this instance is success.
        /// </summary>
        /// <value>
        /// <c>true</c> if this instance is success; otherwise, <c>false</c>.
        /// </value>
        public bool IsSuccess { get; set; } = false;

        /// <summary>
        /// Actual response if succeed 
        /// </summary>
        /// <value>
        /// Actual response if succeed 
        /// </value>
        public object Data { get; set; } = null;

        /// <summary>
        /// Remark if anythig to convey
        /// </summary>
        /// <value>
        /// Remark if anythig to convey
        /// </value>
        public string Remark { get; set; } = string.Empty;
        /// <summary>
        /// Gets or sets the error message.
        /// </summary>
        /// <value>
        /// The error message.
        /// </value>
        public object ErrorMessage { get; set; } = null;


    }  




[HttpGet]
        public IHttpActionResult Employees()
        {
            Response _res = new Response();
            try
            { 
                DalTest objDal = new DalTest(); 
                _res.Data = objDal.GetTestData();
                _res.IsSuccess = true;
                return Ok<Response>(_res);
            }
            catch (Exception ex)
            {
                _res.IsSuccess = false;
                _res.ErrorMessage = ex;
                return ResponseMessage(Request.CreateResponse(HttpStatusCode.InternalServerError, _res )); 
            } 
        }

제안이 있으면 언제든지 환영합니다. :)


-1

답이 늦어서 미안하지만 왜 간단하게 사용하지 않습니까?

return BadRequest("your message");

나는 내 모든 것을 위해 그것을 사용 IHttpActionResult 오류에 잘 사용됩니다.

여기 문서가 있습니다 : https://msdn.microsoft.com/en-us/library/system.web.http.apicontroller.badrequest(v=vs.118).aspx


7
모든 오류가 잘못된 요청의 결과 인 것은 아니기 때문에 400응답이 부적절합니다. OP는 구체적 500으로 예를 들어 응답을 제공했습니다.
user1620220

예, BadRequest 만 가능합니다. 다른 유형은 메시지 인수를받지 않습니다.
benraay
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.