【问题标题】:Return Custom HTTP Status Code from WebAPI 2 endpoint从 WebAPI 2 端点返回自定义 HTTP 状态代码
【发布时间】:2014-06-17 10:24:55
【问题描述】:

我正在开发 WebAPI 2 中的服务,并且端点当前返回 IHttpActionResult。我想返回一个状态码422,但由于它不在HttpStatusCode 枚举中,我不知道如何发送它,因为所有构造函数都需要HttpStatusCode 的参数

就目前而言,我正在返回 BadResult(message),但返回 422 + 消息对我的客户来说更具描述性和有用性。有什么想法吗?

【问题讨论】:

  • 如果您使用 ASP.NET 或 ASP.NET MVC 返回 '(HttpStatusCode)422. That's valid C# but I haven't used WebAPI 2, to be sure it won't be rejected. Otherwise one can certainly return 422 Unprocessable Entity` 和其他 RFC 2616 后状态会发生什么,所以也许可以下拉到在 WebAPI2 中,但我又不知道,所以不能给出完整的答案。我确实知道,在 MVC 中,仅设置 HttpResponse.StatusCode 会自动为 RFC 2616 代码设置正确的状态描述,除此之外,您还需要自己设置“不可处理实体”等。
  • 对不起,为什么要使用422? HTTP 1.1 规范中没有定义!
  • @ToanNguyen 422 在用于 Web 分布式创作和版本控制 (WebDAV) 的 HTTP 扩展中定义 (tools.ietf.org/html/rfc4918#section-11.2) 另请参阅:bennadel.com/blog/…

标签: c# asp.net-web-api http-status-code-404


【解决方案1】:

根据 C# 规范:

枚举类型可以采用的值集不受其枚举成员的限制。特别是,枚举的基础类型的任何值都可以转换为枚举类型,并且是该枚举类型的不同有效值

因此,您可以将状态代码 422 转换为 HttpStatusCode。

示例控制器:

using System.Net;
using System.Net.Http;
using System.Web.Http;

namespace CompanyName.Controllers.Api
{
    [RoutePrefix("services/noop")]
    [AllowAnonymous]
    public class NoOpController : ApiController
    {
        [Route]
        [HttpGet]
        public IHttpActionResult GetNoop()
        {
            return new System.Web.Http.Results.ResponseMessageResult(
                Request.CreateErrorResponse(
                    (HttpStatusCode)422,
                    new HttpError("Something goes wrong")
                )
            );
        }
    }
}

【讨论】:

  • 很好的解决方案。我对此进行了重构,并在控制器上创建了一个返回 IHttpActionResult 的方法。它被简化为'return Status(404,"Some error.")。
【解决方案2】:
 return Content((HttpStatusCode) 422, whatEver);

信用是:Return content with IHttpActionResult for non-OK response

并且您的代码必须是

请忽略 100 到 200 之间的代码。

【讨论】:

  • 你能解释一下为什么我们应该忽略 100 到 200 之间的代码吗?
【解决方案3】:

我用这种方式简洁优雅。

public ActionResult Validate(User user)
{
     return new HttpStatusCodeResult((HttpStatusCode)500, 
               "My custom internal server error.");
}

然后是角度控制器。

function errorCallBack(response) {            
$scope.response = {
   code: response.status,
   text: response.statusText
}});    

希望对您有所帮助。

【讨论】:

  • 此解决方案来自 System.Web.Mvc 命名空间,而不是预期的 System.Web.Http
【解决方案4】:

另一个简化的例子:

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

Content 是定义在抽象类ApiController 中的虚方法,它是控制器的基础。声明如下:

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

【讨论】:

    【解决方案5】:

    为此,您可能需要使用操作过滤器属性。没有什么花哨。只需创建一个类并从 c# 中的ActionFilterAttribute 类继承它。然后重写一个名为OnActionExecuting 的方法来实现它。然后只需在任何控制器的头部使用此过滤器即可。以下是一个演示。

    如果您需要在ActionFilterAttribute 中生成基于自定义状态码的消息,您可以按以下方式编写:

            if (necessity_to_send_custom_code)
            {
                actionContext.Response = actionContext.Request.CreateResponse((HttpStatusCode)855, "This is custom error message for you");
            }
    

    希望这会有所帮助。

    【讨论】:

      【解决方案6】:

      我在我的控制器中使用了一个自定义过滤器来捕获任何异常并返回自定义错误结果,因此我需要一种方法来根据异常消息返回自定义消息响应。

      我正在使用JsonResult(在 Microsoft.AspNetCore.Mvc 命名空间中找到)返回自定义状态代码和消息,例如:

      public class DomainViolationFilter : ExceptionFilterAttribute
          {
              public override void OnException(ExceptionContext context)
              {
                  switch (context.Exception)
                  {
                      case EntityNotFoundException e:
                          JsonResult toReturn = new JsonResult(e);
                          toReturn.StatusCode = 404;
                          context.Result = toReturn;
                          return;
                  }
              }
          }
      

      在我的例子中,为了简单起见,我直接序列化异常对象(ex),但您应该只返回相关(和安全)数据,或者您的用例中需要的任何数据。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-12-02
        • 1970-01-01
        • 2014-10-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-09-08
        相关资源
        最近更新 更多