使用IHttpActionResult返回内容以获取非OK响应


184

对于从Web API 2控制器返回的消息,如果响应正常(状态200),我可以返回包含响应的内容,如下所示:

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

如果可能的话,我想在此处使用内置的结果类型:https : //msdn.microsoft.com/zh-cn/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);
    }

或者,还有更好的方法?



你能不能使用ApiController.InternalServerError msdn.microsoft.com/en-us/library/dn292630(v=vs.118).aspx
Ric

@米兰,谢谢。这样的事情可能会起作用。我不喜欢的部分是,它需要为每个我想使用的现有实现创建一个不同的IHttpActionResult实现。
mayabelle

@Ric,不,该参数是一个异常。我想将消息设置为字符串。而且,这不能解决代码可能不一定是内部服务器错误的更普遍的情况。
mayabelle

3
@mayabelle:您看到了Shamil Yakupov的回答吗?接受的答案更加简单明了。
以撒

Answers:


419

您可以使用此:

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

1
简短的解决方案。拥有更多的代码意味着更多的错误和费时的维护。
Thomas.Benz

6
当我尝试这样做时,code(其中代码是字符串的)in 的返回值return Content(HttpStatusCode.OK, code)被封装在“这是意外的,是否有任何原因?例如,返回的值是"\"value\""我正在使用mvc5
Deza

2
如果您需要从ApiController类之外执行此操作,则可以使用:return new NegotiatedContentResult <T>(code,new T(...),controller)
Etherman

我可以从班级图书馆归还吗?我需要参考什么?
工具包

54

您可以使用HttpRequestMessagesExtensions.CreateErrorResponseSystem.Net.Http名称空间),如下所示:

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

最好根据请求创建响应以利用Web API的内容协商。


6
Request.CreateErrorResponse返回HttpResponseMessage,而不是IHttpActionResult。您所描述的是创建HttpResponseMessage的良好做法,但没有解决我的问题。不管怎么说,还是要谢谢你!
mayabelle

@mayabelle,您可以创建IHttpActionResult具体结构,并像这样包装这些代码:
Quoc Nguyen

1
这对我有用,但是我使用了Request.CreateResponse,因此错误显示为字符串而不是Message键下。
化学家

我遇到错误,代码段失败。它说“请求”为空。我正在尝试使用Request.CreateResponse @ user1620220
Sheena Agrawal,

@SheenaAgrawal该代码只能在HTTP请求的上下文中执行。如果ApiController.Request为null,则意味着您不在正确的上下文中,或者WebAPI体系结构中出现了问题。
user1620220 '18

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 '17

16

您也可以这样做:

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

1
是的,但是要使该消息文本恢复很
麻烦

7

有兴趣通过返回ResponseMessage返回具有任何状态码的任何内容的任何人:

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

7

在ASP.NET Web API 2中,可以将任何内容包装ResponseMessageResponseMessageResult中

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

在某些情况下,这可能是获得所需结果的最简单方法,尽管通常最好在System.Web.Http.Results中使用各种结果。




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

Content是在抽象类ApiController(控制器的基础)中定义的虚拟方法。参见以下声明:

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

以上的事情真的很有帮助。

在创建Web服务时,如果您愿意接受服务,那么消费者将不胜感激。我试图保持输出的一致性。您也可以提供备注或实际错误消息。Web服务使用者只能检查IsSuccess是否为true,否则将确定是否存在问题,并根据情况进行操作。

  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/zh-cn/library/system.web.http.apicontroller.badrequest(v=vs.118).aspx


7
因为并非所有错误都是错误请求的结果,所以400响应将是不合适的。OP专门给出了500响应作为示例。
user1620220 '16

是的,只有使用BadRequest才有可能,其他类型不接受消息参数
benraay
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.