.NET Core Web API: return a custom HTTP status code with Content Type application/problem+json
ControllerBase包含诸如Conflict()之类的方法,这些方法返回从StatusCodeResult派生的ConflictResult对象(代表HTTP 409响应)。结果响应主体的内容类型为application/problem+json,如下所示:
1 2 3 4 5 6
| {
"type":"https://tools.ietf.org/html/rfc7231#section-6.5.8",
"title":"Conflict",
"status": 409,
"traceId":"0HLO99QHFC9QI:00000001"
} |
HTTP 410响应没有内置的方法/类,所以我做了一个:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| [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 ();
}
} |
但是,这给出了
1 2 3 4
| {
"type":"about:blank",
"status": 410
} |
即type值不同,并且title和traceId字段丢失。
我还想为HTTP 500响应创建一个自定义类,该类包括带有错误消息的message字段。我尝试返回StatusCode(StatusCodes.Status500InternalServerError),这给了我与Gone()方法相同的最小application/problem+json响应。我也尝试过返回StatusCode(StatusCodes.Status500InternalServerError, message),这会给我我的错误消息,但是将响应的格式设置为text/plain。
- 您在此处提出的两个问题具有不同的解决方案(imo)。我添加了一个答案来解决410问题,但您在撰写本文时遇到的另一个答案是500问题。我在回答我给出的答案中的第二个问题时并没有多大意义,因为通常只重复其他答案的第二个一半(我会选择不返回明确的500,而是使用异常和内置函数异常处理程序的东西,但这只是我的意见)。
生成ProblemDetails响应的代码不知道410状态代码,因此在构建响应对象时没有关联的Link和Title属性。要添加此意识,请在ConfigureServices中配置ApiBehaviorOptions,如下所示:
1 2 3 4 5 6 7 8
| services .Configure<ApiBehaviorOptions >(options =>
{
options .ClientErrorMapping[410] = new ClientErrorData
{
Title ="Gone",
Link ="https://tools.ietf.org/html/rfc7231#section-6.5.9"
};
}); |
ClientErrorMapping是int(状态代码)到ClientErrorData的字典。请注意,我上面用于Link的值确实指向RFC的正确部分。
-
好的。我认为有某种方法可以做到这一点,但在文档或源代码中找不到任何内容。虽然理所当然,但我并没有花很多时间在寻找。出于好奇,您是否有资料来源可供将来参考?
-
@ChrisPratt在文档中有此内容,在2.2源代码中也有此内容。还有工厂。
-
谢谢。我昨天从字面上看文档中的页面,但仍然以某种方式错过了它。嘘。
简单来说,您实际上必须返回一个ProblemDetails响应主体。我必须仔细检查代码以确保,但是我认为ASP.NET Core仅通过中间件来实现特定结果。他们说的是4xx范围内的任何内容,但我认为实际上只限于返回该范围内状态代码的内置结果类型,而不是带有4xx状态代码的任何结果。同样,这是一种推测,因为我没有确切地查看他们在做什么,尽管这并不是实际结果类的一部分。
出于您的目的,您可以通过几种不同的方式来处理此问题。您可以编写自己的中间件来捕获出站响应并进行重写。您可以使用自定义异常处理程序。您可以直接从ObjectResult继承,然后自己创建一个ProblemDetails实例并将其放入基础中。您甚至可以直接从操作中直接返回ProblemDetails(尽管,这显然是最不理想的方法)。
- 非常感谢克里斯。对于500个错误,我最终实现了一个自定义的异常处理程序,并使用nuget.org/packages/Hellang.Middleware.ProblemDetails包进行繁重的工作-现在,它运行良好。