使用 Swashbuckle.AspNetCore 手动将自定义路由参数添加到 Swagger 文档
Manually add custom route parameter to Swagger docs with Swashbuckle.AspNetCore
所以我遇到了一个有趣的案例,我需要为 REST API 生成 swagger 文档,它的唯一文档是一个实际文档(没有内联 XML 文档)和 我没有直接的源代码访问权限。所以我简单地写了一个包装器控制器,并像这样覆盖每条路线:
[HttpGet("this/{that}/the/{other}")]
public override IActionResult GetWhatever(String that, String other) => base.GetWhatever(that, other);
然后用标准摘要标签等记录它。但是,现在覆盖的方法之一在内部使用查询字符串,并且没有作为 [FromQuery] 的参数公开,因此它不能自动-反射式记录(并在没有实际参数的情况下为其添加标签不会为其生成文档)
我需要一种方法来手动添加此参数文档,但要以某种方式通过代码(不仅仅是将其添加到 swagger.json 文件)。我虽然可以使用 SwaggerGen 的 ISchemaFilter 向关联的 route/method 添加参数描述,但到目前为止我运气不佳。
有没有人有这样的例子?
看来我要找的是 IOpertationFilter。将其与自定义属性相结合,我能够创建我需要的内容,以便即时将自定义参数手动添加到 Swagger 文档中。查看下面所有相关代码,请注意 Schema/PartialSchema 有很多属性,我只设置了类型,因为它是我所需要的,其他情况可能需要更多。
SwaggerParameterAttribute.cs
using System;
using Microsoft.AspNetCore.Mvc.Filters;
using Swashbuckle.AspNetCore.Swagger;
/// <summary>
/// Types of Swagger parameters
/// </summary>
public enum SwaggerParamType {Body, NonBody};
/// <summary>
/// Attribute to facilitate manually adding a parameter to auto-generated Swagger documentation
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class SwaggerParameterAttribute : ActionFilterAttribute {
/// <summary>
/// Swagger parameter to inject
/// </summary>
public IParameter Parameter { get; set; }
/// <summary>
/// Default constructor
/// </summary>
/// <param name="ParamType">Type of Swagger parameter (Body/NonBody)</param>
/// <param name="Name">Name of the parameter</param>
/// <param name="Type">Primitive type associated with the parameter (int, bool, string, etc.)</param>
/// <param name="In">Location of the parameter (path, query, etc.)</param>
/// <param name="Description">Description of the parameter</param>
/// <param name="Required">Whether the parameter is required or not (true/false)</param>
public SwaggerParameterAttribute(SwaggerParamType ParamType, String Name, String Type, String In, String Description = "", Boolean Required = false){
switch (ParamType) {
case SwaggerParamType.Body:
Parameter = new BodyParameter() { Name = Name, In = In, Description = Description, Required = Required, Schema = new Schema() { Type = Type } };
break;
case SwaggerParamType.NonBody:
Parameter = new NonBodyParameter() { Name = Name, In = In, Description = Description, Required = Required };
((PartialSchema)Parameter).Type = Type;
break;
default:
throw new ArgumentOutOfRangeException("Invalid Swagger parameter type specified.");
}
}
SwaggerOperationFilter.cs
using System;
using System.Reflection;
using Microsoft.AspNetCore.Mvc.Controllers;
using Swashbuckle.AspNetCore.Swagger;
using Swashbuckle.AspNetCore.SwaggerGen;
using Whatever.NameSpace.Your.Attribute.Is.In;
/// <summary>
/// Custom Swagger Operation Filter
/// </summary>
public class SwaggerOperationFilter : IOperationFilter {
public void Apply(Operation operation, OperationFilterContext context) {
//Check for [SwaggerParameter] add defined parameter to the parameter list
foreach (Attribute attribute in ((ControllerActionDescriptor)context.ControllerActionDescriptor).MethodInfo.GetCustomAttributes()) {
if (attribute.GetType() == typeof(SwaggerParameterAttribute)) {
operation.Parameters.Add(((SwaggerParameterAttribute)attribute).Parameter);
}
}
}
}
Startup.cs(只是swagger操作过滤部分)
using Swashbuckle.AspNetCore.Swagger;
using Whatever.NameSpace.Your.Filter.Is.In;
public void ConfigureServices(IServiceCollection services) {
services.AddSwaggerGen(options => {
options.OperationFilter<SwaggerOperationFilter>();
}
}
SomeController.cs(用法示例)
using Swashbuckle.AspNetCore.Swagger;
using Swashbuckle.AspNetCore.SwaggerGen;
using Whatever.NameSpace.Your.Attribute.Is.In;
[HttpGet("this/{that}/the/{other}")]
[SwaggerParameter(ParamType: SwaggerParamType.NonBody, Name: "param1", Type: "string", In: "query", Description: "Some description of param1 here")]
[SwaggerParameter(SwaggerParamType.NonBody, "param2", "string", "query", "Some description of param2 here")]
public override IActionResult GetWhatever(String that, String other) => base.GetWhatever(that, other);
所以我遇到了一个有趣的案例,我需要为 REST API 生成 swagger 文档,它的唯一文档是一个实际文档(没有内联 XML 文档)和 我没有直接的源代码访问权限。所以我简单地写了一个包装器控制器,并像这样覆盖每条路线:
[HttpGet("this/{that}/the/{other}")]
public override IActionResult GetWhatever(String that, String other) => base.GetWhatever(that, other);
然后用标准摘要标签等记录它。但是,现在覆盖的方法之一在内部使用查询字符串,并且没有作为 [FromQuery] 的参数公开,因此它不能自动-反射式记录(并在没有实际参数的情况下为其添加标签不会为其生成文档)
我需要一种方法来手动添加此参数文档,但要以某种方式通过代码(不仅仅是将其添加到 swagger.json 文件)。我虽然可以使用 SwaggerGen 的 ISchemaFilter 向关联的 route/method 添加参数描述,但到目前为止我运气不佳。
有没有人有这样的例子?
看来我要找的是 IOpertationFilter。将其与自定义属性相结合,我能够创建我需要的内容,以便即时将自定义参数手动添加到 Swagger 文档中。查看下面所有相关代码,请注意 Schema/PartialSchema 有很多属性,我只设置了类型,因为它是我所需要的,其他情况可能需要更多。
SwaggerParameterAttribute.cs
using System;
using Microsoft.AspNetCore.Mvc.Filters;
using Swashbuckle.AspNetCore.Swagger;
/// <summary>
/// Types of Swagger parameters
/// </summary>
public enum SwaggerParamType {Body, NonBody};
/// <summary>
/// Attribute to facilitate manually adding a parameter to auto-generated Swagger documentation
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class SwaggerParameterAttribute : ActionFilterAttribute {
/// <summary>
/// Swagger parameter to inject
/// </summary>
public IParameter Parameter { get; set; }
/// <summary>
/// Default constructor
/// </summary>
/// <param name="ParamType">Type of Swagger parameter (Body/NonBody)</param>
/// <param name="Name">Name of the parameter</param>
/// <param name="Type">Primitive type associated with the parameter (int, bool, string, etc.)</param>
/// <param name="In">Location of the parameter (path, query, etc.)</param>
/// <param name="Description">Description of the parameter</param>
/// <param name="Required">Whether the parameter is required or not (true/false)</param>
public SwaggerParameterAttribute(SwaggerParamType ParamType, String Name, String Type, String In, String Description = "", Boolean Required = false){
switch (ParamType) {
case SwaggerParamType.Body:
Parameter = new BodyParameter() { Name = Name, In = In, Description = Description, Required = Required, Schema = new Schema() { Type = Type } };
break;
case SwaggerParamType.NonBody:
Parameter = new NonBodyParameter() { Name = Name, In = In, Description = Description, Required = Required };
((PartialSchema)Parameter).Type = Type;
break;
default:
throw new ArgumentOutOfRangeException("Invalid Swagger parameter type specified.");
}
}
SwaggerOperationFilter.cs
using System;
using System.Reflection;
using Microsoft.AspNetCore.Mvc.Controllers;
using Swashbuckle.AspNetCore.Swagger;
using Swashbuckle.AspNetCore.SwaggerGen;
using Whatever.NameSpace.Your.Attribute.Is.In;
/// <summary>
/// Custom Swagger Operation Filter
/// </summary>
public class SwaggerOperationFilter : IOperationFilter {
public void Apply(Operation operation, OperationFilterContext context) {
//Check for [SwaggerParameter] add defined parameter to the parameter list
foreach (Attribute attribute in ((ControllerActionDescriptor)context.ControllerActionDescriptor).MethodInfo.GetCustomAttributes()) {
if (attribute.GetType() == typeof(SwaggerParameterAttribute)) {
operation.Parameters.Add(((SwaggerParameterAttribute)attribute).Parameter);
}
}
}
}
Startup.cs(只是swagger操作过滤部分)
using Swashbuckle.AspNetCore.Swagger;
using Whatever.NameSpace.Your.Filter.Is.In;
public void ConfigureServices(IServiceCollection services) {
services.AddSwaggerGen(options => {
options.OperationFilter<SwaggerOperationFilter>();
}
}
SomeController.cs(用法示例)
using Swashbuckle.AspNetCore.Swagger;
using Swashbuckle.AspNetCore.SwaggerGen;
using Whatever.NameSpace.Your.Attribute.Is.In;
[HttpGet("this/{that}/the/{other}")]
[SwaggerParameter(ParamType: SwaggerParamType.NonBody, Name: "param1", Type: "string", In: "query", Description: "Some description of param1 here")]
[SwaggerParameter(SwaggerParamType.NonBody, "param2", "string", "query", "Some description of param2 here")]
public override IActionResult GetWhatever(String that, String other) => base.GetWhatever(that, other);