在 ASP.NET Core 中为未绑定参数添加 swagger 参数
Add swagger parameters for unbound parameters in ASP.NET Core
我有一个 ASP.NET Core 2.2 WebApi,我想上传带有一些额外元数据的大文件。请求是 multipart/form-data。因为要上传的文件可能会变得非常大,所以我不想将其读入内存进行处理,而是直接将其流式传输到所需的目的地。
我按照 documentation 禁用表单值模型绑定,我还调整了端点的最大请求大小。
我已经用 postman 测试了端点,它按预期工作:
但是,Swagger显然不承认请求应该有参数。如何在不在方法签名中定义参数的情况下将这些参数添加到 swagger 文档中?
我的端点类似于以下示例:
[HttpPost]
[DisableFormValueModelBinding]
[DisableRequestSizeLimit]
public async Task<IActionResult> Upload() // "department" and "file" needed in the multipart/form-data
{
// var path = await uploader.UploadAsync(Request);
// return Ok(path);
}
通常,我会像下面的例子那样绑定参数:
public async Task<IActionResult> Upload([FromForm] string department, [FromForm] IFormFile file)
这在 Swagger 中按预期工作,但如上所述,我不想绑定参数。
您可以为此使用 IOperationFilter
。添加以下内容class,调整控制器和动作名称
public class AddUnboundParametersOperationFilter : IOperationFilter
{
public void Apply(Operation operation, OperationFilterContext context)
{
if (operation.Parameters == null)
operation.Parameters = new List<IParameter>();
var descriptor = context.ApiDescription.ActionDescriptor as ControllerActionDescriptor;
if (descriptor != null && descriptor.ControllerTypeInfo == typeof(TestController) && descriptor.ActionName == nameof(TestController.Upload))
{
operation.Parameters.Add(new NonBodyParameter()
{
Name = "department",
Type = "string",
Required = true,
In = "formData",
});
operation.Parameters.Add(new NonBodyParameter()
{
Type = "file",
In = "formData",
Name = "file",
Required = true
});
}
}
}
在Startup.cs
services.AddSwaggerGen(c =>
{
c.OperationFilter<AddUnboundParametersOperationFilter>();
//...
});
对于 Swashbuckle.AspNetCore 版本 5 及更高版本,一些内容已更改。
要像 Alexander 在他的回答中那样提供参数,代码将如下所示:
operation.Parameters.Add(new OpenApiParameter()
{
Name = "department",
Schema = new OpenApiSchema { Type = "string", Format = "string" },
Required = true,
});
operation.Parameters.Add(new OpenApiParameter()
{
Name = "file",
Schema = new OpenApiSchema { Type = "string", Format = "binary" },
Required = true,
});
但是出于某种原因(我没有进一步调查),我无法使用这种方法在 Swagger UI 中执行调用。
最后,以下示例为我提供了我正在寻找的结果:
public class AddUnboundParametersOperationFilter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
var descriptor = context.ApiDescription.ActionDescriptor as ControllerActionDescriptor;
if (descriptor != null && descriptor.ControllerTypeInfo == typeof(RemoteUpdateController) && descriptor.ActionName == nameof(RemoteUpdateController.Upload))
{
var openApiMediaType = new OpenApiMediaType
{
Schema = new OpenApiSchema
{
Type = "object",
Required = new HashSet<string> { "department", "file" }, // make the parameter(s) required if needed
Properties = new Dictionary<string, OpenApiSchema>
{
{ "department" , new OpenApiSchema() { Type = "string", Format = "string" } },
{ "file" , new OpenApiSchema() { Type = "string", Format = "binary" } },
}
}
};
operation.RequestBody = new OpenApiRequestBody
{
Content = new Dictionary<string, OpenApiMediaType>
{
{ "multipart/form-data", openApiMediaType }
}
};
}
}
}
我有一个 ASP.NET Core 2.2 WebApi,我想上传带有一些额外元数据的大文件。请求是 multipart/form-data。因为要上传的文件可能会变得非常大,所以我不想将其读入内存进行处理,而是直接将其流式传输到所需的目的地。 我按照 documentation 禁用表单值模型绑定,我还调整了端点的最大请求大小。
我已经用 postman 测试了端点,它按预期工作:
但是,Swagger显然不承认请求应该有参数。如何在不在方法签名中定义参数的情况下将这些参数添加到 swagger 文档中?
我的端点类似于以下示例:
[HttpPost]
[DisableFormValueModelBinding]
[DisableRequestSizeLimit]
public async Task<IActionResult> Upload() // "department" and "file" needed in the multipart/form-data
{
// var path = await uploader.UploadAsync(Request);
// return Ok(path);
}
通常,我会像下面的例子那样绑定参数:
public async Task<IActionResult> Upload([FromForm] string department, [FromForm] IFormFile file)
这在 Swagger 中按预期工作,但如上所述,我不想绑定参数。
您可以为此使用 IOperationFilter
。添加以下内容class,调整控制器和动作名称
public class AddUnboundParametersOperationFilter : IOperationFilter
{
public void Apply(Operation operation, OperationFilterContext context)
{
if (operation.Parameters == null)
operation.Parameters = new List<IParameter>();
var descriptor = context.ApiDescription.ActionDescriptor as ControllerActionDescriptor;
if (descriptor != null && descriptor.ControllerTypeInfo == typeof(TestController) && descriptor.ActionName == nameof(TestController.Upload))
{
operation.Parameters.Add(new NonBodyParameter()
{
Name = "department",
Type = "string",
Required = true,
In = "formData",
});
operation.Parameters.Add(new NonBodyParameter()
{
Type = "file",
In = "formData",
Name = "file",
Required = true
});
}
}
}
在Startup.cs
services.AddSwaggerGen(c =>
{
c.OperationFilter<AddUnboundParametersOperationFilter>();
//...
});
对于 Swashbuckle.AspNetCore 版本 5 及更高版本,一些内容已更改。
要像 Alexander 在他的回答中那样提供参数,代码将如下所示:
operation.Parameters.Add(new OpenApiParameter()
{
Name = "department",
Schema = new OpenApiSchema { Type = "string", Format = "string" },
Required = true,
});
operation.Parameters.Add(new OpenApiParameter()
{
Name = "file",
Schema = new OpenApiSchema { Type = "string", Format = "binary" },
Required = true,
});
但是出于某种原因(我没有进一步调查),我无法使用这种方法在 Swagger UI 中执行调用。
最后,以下示例为我提供了我正在寻找的结果:
public class AddUnboundParametersOperationFilter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
var descriptor = context.ApiDescription.ActionDescriptor as ControllerActionDescriptor;
if (descriptor != null && descriptor.ControllerTypeInfo == typeof(RemoteUpdateController) && descriptor.ActionName == nameof(RemoteUpdateController.Upload))
{
var openApiMediaType = new OpenApiMediaType
{
Schema = new OpenApiSchema
{
Type = "object",
Required = new HashSet<string> { "department", "file" }, // make the parameter(s) required if needed
Properties = new Dictionary<string, OpenApiSchema>
{
{ "department" , new OpenApiSchema() { Type = "string", Format = "string" } },
{ "file" , new OpenApiSchema() { Type = "string", Format = "binary" } },
}
}
};
operation.RequestBody = new OpenApiRequestBody
{
Content = new Dictionary<string, OpenApiMediaType>
{
{ "multipart/form-data", openApiMediaType }
}
};
}
}
}