从 WebAPI 2 终结点返回自定义 HTTP 状态代码

本文关键字:自定义 HTTP 状态 代码 返回 结点 WebAPI | 更新日期: 2023-09-27 18:00:57

我正在 WebAPI 2 中处理一项服务,端点当前返回一个IHttpActionResult . 我想返回一个状态代码422,但由于它不在HttpStatusCode枚举中,我对如何发送它感到茫然,因为所有构造函数都需要一个参数HttpStatusCode

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

从 WebAPI 2 终结点返回自定义 HTTP 状态代码

根据 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")
                )
            );
        }
    }
}
 return Content((HttpStatusCode) 422, whatEver);

信用用于:返回具有 IHttpActionResult 的内容,用于非正常响应

并且您的代码必须为 <= 999

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

我用这种方式简单而优雅。

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

希望对您有所帮助。

另一个简化的例子:

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

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

我正在使用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;
            }
        }
    }

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

为此

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

在需要生成基于自定义状态代码的消息的情况下ActionFilterAttribute您可以通过以下方式编写:

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

希望这有帮助。

这适用于 2023 年的 C#,而较旧的示例似乎不适用于内容,因为第一个参数必须是字符串内容。

var response = Content("We cannot process this");
response.StatusCode = 422;
return response; 

这里的很多答案直接使用强制转换或整数。

但是,您也可以使用Microsoft.AspNetCore.Http.StatusCodes并恢复具有引用类型安全性的额外好处的int

示例:return Content(StatusCodes.Status422UnprocessableEntity, ...);