如何使用错误消息或异常返回NotFound()IHttpActionResult?

Aja*_*hav 92 c# httpresponse http-status-code-404 asp.net-web-api

IHttpActionResult当我的WebApi GET操作中找不到某些内容时,我将返回NotFound .除了这个响应,我想发送自定义消息和/或异常消息(如果有的话).当前ApiControllerNotFound()方法不提供传递消息的重载.

有没有办法做到这一点?或者我将不得不写自己的习惯IHttpActionResult

Ant*_*y F 216

这是一个用于返回带有简单消息的IHttpActionResult NotFound的单行程序:

return Content(HttpStatusCode.NotFound, "Foo does not exist.");
Run Code Online (Sandbox Code Playgroud)

  • 人们应该投票给这个答案.这很好,很容易! (23认同)
  • @KasperHalvasJensen服务器的http状态代码是404,你还需要更多东西吗? (4认同)
  • @AnthonyF你是对的.我正在使用Controller.Content(...).Shoud使用了ApiController.Content(...) - 我的不好. (4认同)
  • 请注意,此解决方案不会将HTTP标头状态设置为"404 Not Found". (2认同)

dma*_*son 81

如果要自定义响应消息形状,则需要编写自己的操作结果.

我们希望提供开箱即用的最常见的响应消息形状,例如简单的空404,但我们也希望保持这些结果尽可能简单; 使用动作结果的一个主要优点是它使您的动作方法更容易进行单元测试.我们在操作结果上添加的属性越多,您的单元测试需要考虑的事项越多,以确保操作方法正在执行您期望的操作.

我经常希望能够提供自定义消息,因此请随时记录一个错误,以便我们考虑在将来的版本中支持该操作结果:https: //aspnetwebstack.codeplex.com/workitem/list/advanced

但是,关于动作结果的一个好处是,如果你想做一些稍微不同的事情,你可以很容易地写自己的.以下是您可以在您的情况下执行此操作(假设您需要text/plain中的错误消息;如果您想要JSON,则会对内容执行稍微不同的操作):

public class NotFoundTextPlainActionResult : IHttpActionResult
{
    public NotFoundTextPlainActionResult(string message, HttpRequestMessage request)
    {
        if (message == null)
        {
            throw new ArgumentNullException("message");
        }

        if (request == null)
        {
            throw new ArgumentNullException("request");
        }

        Message = message;
        Request = request;
    }

    public string Message { get; private set; }

    public HttpRequestMessage Request { get; private set; }

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

    public HttpResponseMessage Execute()
    {
        HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.NotFound);
        response.Content = new StringContent(Message); // Put the message in the response body (text/plain content).
        response.RequestMessage = Request;
        return response;
    }
}

public static class ApiControllerExtensions
{
    public static NotFoundTextPlainActionResult NotFound(this ApiController controller, string message)
    {
        return new NotFoundTextPlainActionResult(message, controller.Request);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,在您的操作方法中,您可以执行以下操作:

public class TestController : ApiController
{
    public IHttpActionResult Get()
    {
        return this.NotFound("These are not the droids you're looking for.");
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您使用自定义控制器基类(而不是直接从ApiController继承),您也可以消除"this".part(调用扩展方法时不幸需要):

public class CustomApiController : ApiController
{
    protected NotFoundTextPlainActionResult NotFound(string message)
    {
        return new NotFoundTextPlainActionResult(message, Request);
    }
}

public class TestController : CustomApiController
{
    public IHttpActionResult Get()
    {
        return NotFound("These are not the droids you're looking for.");
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 此功能应该是开箱即用的.包含可选的"ResponseBody"参数不应影响单元测试. (5认同)

Kir*_*lla 28

ResponseMessageResult如果你愿意,你可以使用:

var myCustomMessage = "your custom message which would be sent as a content-negotiated response"; 
return ResponseMessage(
    Request.CreateResponse(
        HttpStatusCode.NotFound, 
        myCustomMessage
    )
);
Run Code Online (Sandbox Code Playgroud)

是的,如果你需要更短的版本,那么我想你需要实现你的自定义动作结果.


Dmy*_*nko 7

您可以使用HttpResponseMessage类的ReasonPhrase属性

catch (Exception exception)
{
  throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound)
  {
    ReasonPhrase = exception.Message
  });
}
Run Code Online (Sandbox Code Playgroud)


小智 5

ASP.NET Core中的一行代码:

Return StatusCode(404, "Not a valid request.");
Run Code Online (Sandbox Code Playgroud)