为多个 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; }
属性,它同时用于ProducesAttribute
和ProducesResponseTypeAttribute
.
但是,在您的特殊情况下,您可以将其注册为全局过滤器,因为无论是 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 响应类型和代码。
它已经带有一套很好的默认约定,但您也可以覆盖它并提供您自己的约定方法。
我正在设置 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; }
属性,它同时用于ProducesAttribute
和ProducesResponseTypeAttribute
.
但是,在您的特殊情况下,您可以将其注册为全局过滤器,因为无论是 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 响应类型和代码。
它已经带有一套很好的默认约定,但您也可以覆盖它并提供您自己的约定方法。