Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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:

[HttpPost]
[Route("api/upload")]
[Consumes("multipart/form-data")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task<IActionResult> UploadDataAsync()
{
    // Use the HttpContext.Request.Body to read the body manually

    return NoContent();
}

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

[HttpPost]
[Route("api/upload")]
[Consumes("multipart/form-data")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[SwaggerRequestBody(typeof(SomeDTO))] /* Something like this attribute! */
public async Task<IActionResult> UploadDataAsync()
{
    // Use the HttpContext.Request.Body to read the body manually

    return NoContent();
}

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.

like image 990
Khodaie Avatar asked Sep 12 '25 23:09

Khodaie


1 Answers

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

public sealed class AnyBodyFilter<T> : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        var schema = context.SchemaGenerator.GenerateSchema(typeof(T), context.SchemaRepository);

        operation.RequestBody = new OpenApiRequestBody
        {
            Content =
            {
                ["multipart/form-data"] = new OpenApiMediaType
                {
                    Schema = schema,
                }
            }
        };
    }
}

Then decorate your action with attribute [SwaggerOperationFilter(typeof(AnyBodyFilter<SomeDTO>))] and it's should be done.

like image 137
stukselbax Avatar answered Sep 15 '25 13:09

stukselbax