【问题标题】:.NET Core Web API: return a custom HTTP status code with Content Type application/problem+json.NET Core Web API:返回内容类型为 application/problem+json 的自定义 HTTP 状态代码
【发布时间】:2019-07-15 18:18:49
【问题描述】:

ControllerBase 包含诸如 Conflict() 之类的方法,这些方法返回从 StatusCodeResult 派生的 ConflictResult 对象(表示 HTTP 409 响应)。生成的响应正文的内容类型为 application/problem+json,如下所示:

{
    "type": "https://tools.ietf.org/html/rfc7231#section-6.5.8",
    "title": "Conflict",
    "status": 409,
    "traceId": "0HLO99QHFC9QI:00000001"
}

没有用于 HTTP 410 响应的内置方法/类,所以我做了一个:

[DefaultStatusCode(410)]
public class GoneResult : StatusCodeResult
{
    public GoneResult() : base(410)
    {}
}
...
public static class ControllerBaseExtensions
{
    public static GoneResult Gone(this ControllerBase controllerBase) // this doesn't give all the problem+JSON attributes
    {
        return new GoneResult();
    }
}

然而,这给了

{
    "type": "about:blank",
    "status": 410
}

即,type 值不同,titletraceId 字段丢失。

我还想为 HTTP 500 响应创建一个自定义类,其中包含带有错误消息的 message 字段。我尝试返回StatusCode(StatusCodes.Status500InternalServerError),这给了我与Gone() 方法相同的最小application/problem+json 响应;我也尝试过返回StatusCode(StatusCodes.Status500InternalServerError, message),这给了我错误消息,但将响应格式化为text/plain

【问题讨论】:

  • 您在这里提出的两个问题有不同的解决方案 (imo)。我添加了一个解决 410 问题的答案,但您拥有的另一个答案(在撰写本文时)解决了 500 问题。我认为在我给出的答案中解决第二个问题没有多大意义,因为它通常只是重复另一个答案的第二半(我会去不返回明确的 500s,而是使用异常和内置异常处理程序的东西,但这只是我的意见)。

标签: c# asp.net-core asp.net-core-webapi


【解决方案1】:

生成ProblemDetails 响应的代码不知道410 状态码,因此它没有关联的LinkTitle 属性在构建响应对象时使用。要添加这种感知,请在ConfigureServices 中配置ApiBehaviorOptions,如下所示:

services.Configure<ApiBehaviorOptions>(options =>
{
    options.ClientErrorMapping[410] = new ClientErrorData
    {
        Title = "Gone",
        Link = "https://tools.ietf.org/html/rfc7231#section-6.5.9"
    };
});

ClientErrorMappingint(状态码)到ClientErrorData 的字典。请注意,我在上面用于 Link 的值确实指向了 RFC 的正确部分。

【讨论】:

  • 不错。我认为有某种方法可以做到这一点,但在文档或源代码中找不到任何内容。不过,当然,我并没有花很多时间去寻找。出于好奇,您是否有来源供将来参考?
  • @ChrisPratt 文档中有this,2.2 源中有this。还有factory
  • 谢谢。我昨天确实在查看文档中的页面,但仍然不知何故错过了它。嘘。
【解决方案2】:

简单地说,您必须实际返回一个ProblemDetails 响应正文。我必须深入研究代码才能确定,但​​我认为 ASP.NET Core 通过中间件执行此操作只是为了特定结果。他们 4xx 范围内的任何内容,但我认为这实际上仅限于返回该范围内状态代码的内置结果类型,而不是任何 4xx 的结果状态码。同样,这是猜想,因为我还没有看到他们在做什么,尽管它不是作为实际结果类的一部分发生的。

出于您的目的,您可以通过几种不同的方式来处理此问题。您可以编写自己的中间件来捕获出站响应并重写它们。您可以使用自定义异常处理程序。您可以简单地从ObjectResult 继承,然后自己创建一个ProblemDetails 实例并将其放入基础中。您甚至可以直接从您的操作中返回 ProblemDetails(不过,这显然是最不理想的方式)。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-12
  • 1970-01-01
  • 2014-06-17
相关资源
最近更新 更多