为多个 HttpStatusCodes 设置一个 ProducesResponseType typeof

Set one ProducesResponseType typeof for several HttpStatusCodes

我正在设置 ProducesResponseType,以便使用 Swagger 对其进行记录。

如果响应成功 (OK => 200),则会生成一个 IEnumerable。

[ProducesResponseType(typeof(IEnumerable<MyModel>), 200)]

但是当我遇到异常时,我会捕获它,然后生成一个我的自定义 APIError class 的对象。当我填充对象时,我可以设置不同的 HttpStatusCodes,但最后,我想要的是能够为所有剩余的 HttpStatusCodes 设置 ProducesResponseType 是我的 APIError class。我的意思是,我可以获得 BadRequest、ServerInternalError、Forbidden 等,但它们都将具有相同的响应类型 (ApiError)。有没有办法为所有错误的http代码设置这行代码?还是需要一个一个设置?

[ProducesResponseType(typeof(ApiError), ???)]

最终结果应该是这样的:

[ProducesResponseType(typeof(IEnumerable<MyModel>), 200)]
[ProducesResponseType(typeof(ApiError), AllFailureHttpCodes)]

我担心这是不可能的,至少不是每个动作。

IApiResponseMetadataProvider(参见here)仅定义了一个int StatusCode { get; } 属性,它同时用于ProducesAttributeProducesResponseTypeAttribute .

但是,在您的特殊情况下,您可以将其注册为全局过滤器,因为无论是 GET、POST、PUT 还是 DELETE,所有操作的错误结果都应该相同。

services.AddMvc(options =>
{
    options.Filters.Add(new Microsoft.AspNetCore.Mvc.ProducesResponseTypeAttribute(typeof(ApiError), 400));
    options.Filters.Add(new Microsoft.AspNetCore.Mvc.ProducesResponseTypeAttribute(typeof(ApiError), 401));
    options.Filters.Add(new Microsoft.AspNetCore.Mvc.ProducesResponseTypeAttribute(typeof(ApiError), 409));
});

然后应将这些应用于 MVC/WebAPI 应用程序中的每个操作。

警告语

但是,我个人认为这种用法是错误的,因为它表明您的每个方法都可以处理这些类型的错误。例如 409 专门用于冲突,在 WebAPI 中使用它,当更新资源时出现错误,即当使用乐观并发时,记录被另一个用户更改,因此记录的版本已更改,更新失败。

将这些添加到每个方法都是错误的。如果您的操作确实处理了此状态代码,则您应该只添加状态代码。例如,409 仅适用于 PUT 和 POST 方法。其中 404 可能适合 GET 和 PUT(更新),但不太适合 POST(插入)。

这尤其糟糕,当您使用 Swagger 等工具生成 Api 文档时,您只会得到错误的文档。您应该将 ProducesResponseType 视为一种文档形式,因此不应使用过于通用的方法。

更新:ASP.NET核心 2.2

有了 ASP.NET Core 2.2,Swagger API 支持得到了极大改进,这还包括 convention based 响应类型和代码。

它已经带有一套很好的默认约定,但您也可以覆盖它并提供您自己的约定方法。