Swashbuckle/Swagger: How to declare a custom type for OpenAPI annotations without using it as a request parameter

huangapple go评论148阅读模式
英文:

Swashbuckle/Swagger: How to declare a custom type for OpenAPI annotations without using it as a request parameter

问题

在我的ASP.NET Core应用程序中,我有一个需要手动加载请求正文作为流的操作,使用HttpContext.Request.Body。在这种情况下,我无法使用DTO作为请求参数。但是,尽管DTO不会用于处理请求正文,我仍然希望为OpenAPI注释和文档目的声明自定义类型。

以下是当前的代码片段:

  1. [HttpPost]
  2. [Route("api/upload")]
  3. [Consumes("multipart/form-data")]
  4. [ProducesResponseType(StatusCodes.Status204NoContent)]
  5. public async Task<IActionResult> UploadDataAsync()
  6. {
  7. // 使用HttpContext.Request.Body手动读取请求正文
  8. return NoContent();
  9. }

我需要声明一个自定义类型作为我的请求载荷,类似于这样:

  1. [HttpPost]
  2. [Route("api/upload")]
  3. [Consumes("multipart/form-data")]
  4. [ProducesResponseType(StatusCodes.Status204NoContent)]
  5. [SwaggerRequestBody(typeof(SomeDTO))] /* 类似于这个属性! */
  6. public async Task<IActionResult> UploadDataAsync()
  7. {
  8. // 使用HttpContext.Request.Body手动读取请求正文
  9. return NoContent();
  10. }

请注意,DTO仅用于指定OpenAPI注释,实际上并未在请求处理中使用。

是否有一种方法可以在不使用DTO作为请求参数的情况下实现这一点?我想要确保准确的API文档,同时仍然可以手动处理HttpContext.Request.Body。我知道可以实现自定义的IOperationFilter,但这将需要手动创建带有所有属性的模式。我正在寻找一种避免手动创建模式的更简单方法。

英文:

I have an action in my ASP.NET Core application that needs to manually load the request body as a stream using HttpContext.Request.Body. In this case, I cannot use a DTO as a request parameter. However, I would still like to declare a custom type for OpenAPI annotations and documentation purposes, even though the DTO won't be used to handle the request body.

Here is the current code snippet:

  1. [HttpPost]
  2. [Route(&quot;api/upload&quot;)]
  3. [Consumes(&quot;multipart/form-data&quot;)]
  4. [ProducesResponseType(StatusCodes.Status204NoContent)]
  5. public async Task&lt;IActionResult&gt; UploadDataAsync()
  6. {
  7. // Use the HttpContext.Request.Body to read the body manually
  8. return NoContent();
  9. }

I need to declare a custom type as my request payload. Something like this:

  1. [HttpPost]
  2. [Route(&quot;api/upload&quot;)]
  3. [Consumes(&quot;multipart/form-data&quot;)]
  4. [ProducesResponseType(StatusCodes.Status204NoContent)]
  5. [SwaggerRequestBody(typeof(SomeDTO))] /* Something like this attribute! */
  6. public async Task&lt;IActionResult&gt; UploadDataAsync()
  7. {
  8. // Use the HttpContext.Request.Body to read the body manually
  9. return NoContent();
  10. }

Please note that the DTO is only used for specifying the OpenAPI annotations and is not actually used in the request processing.

Is there a way to achieve this without using the DTO as a request parameter? I want to ensure accurate API documentation while still manually handling the request body using HttpContext.Request.Body. I'm aware that I can implement a custom IOperationFilter, but this would require manually creating the schema with all of the properties. I'm looking for a simpler approach that avoids the need to create the schema myself.

答案1

得分: 2

这里是如何使用IOperationFilter来定义自己的请求体合同的想法:

  1. public sealed class AnyBodyFilter<T> : IOperationFilter
  2. {
  3. public void Apply(OpenApiOperation operation, OperationFilterContext context)
  4. {
  5. var schema = context.SchemaGenerator.GenerateSchema(typeof(T), context.SchemaRepository);
  6. operation.RequestBody = new OpenApiRequestBody
  7. {
  8. Content =
  9. {
  10. ["multipart/form-data"] = new OpenApiMediaType
  11. {
  12. Schema = schema,
  13. }
  14. }
  15. };
  16. }
  17. }

然后,在您的操作上使用[SwaggerOperationFilter(typeof(AnyBodyFilter<SomeDTO>))]属性进行装饰,就应该完成了。

英文:

Here the idea how you can use IOperationFilter to define your own contract for body:

  1. public sealed class AnyBodyFilter&lt;T&gt; : IOperationFilter
  2. {
  3. public void Apply(OpenApiOperation operation, OperationFilterContext context)
  4. {
  5. var schema = context.SchemaGenerator.GenerateSchema(typeof(T), context.SchemaRepository);
  6. operation.RequestBody = new OpenApiRequestBody
  7. {
  8. Content =
  9. {
  10. [&quot;multipart/form-data&quot;] = new OpenApiMediaType
  11. {
  12. Schema = schema,
  13. }
  14. }
  15. };
  16. }
  17. }

Then decorate your action with attribute [SwaggerOperationFilter(typeof(AnyBodyFilter&lt;SomeDTO&gt;))] and it's should be done.

huangapple
  • 本文由 发表于 2023年6月19日 19:10:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/76506065.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定