使用Swashbuckle.AspNetCore手动将自定义路由参数添加到Swagger文档

时间:2018-08-29 17:05:11

标签: swashbuckle asp.net-core-2.1 swagger-codegen

所以我遇到了一个有趣的案例,我需要为REST API生成庞大的文档,而REST API的唯一文档是实际文档(没有内联XML文档)。我没有直接的来源代码访问。所以我简单地写了一个包装控制器,并像这样覆盖了每个路由:

[HttpGet("this/{that}/the/{other}")]
public override IActionResult GetWhatever(String that, String other) => base.GetWhatever(that, other);

,然后使用标准的摘要标记等对其进行文档化。但是,现在被覆盖的方法之一在内部使用查询字符串,并且[FromQuery]并未将其公开为参数,因此无法将其自动记录下来。反思地(在没有实际参数的情况下为其添加标签不会为其生成文档)

我需要一种手动添加此参数文档的方法,但是可以通过某种方式通过代码(不仅是将其添加到swagger.json文件中)。虽然我可以使用SwaggerGen的ISchemaFilter向关联的路由/方法添加参数描述,但是到目前为止我运气不高。

有人有做这样的事的例子吗?

1 个答案:

答案 0 :(得分:1)

因此,看来我正在寻找的是 IOpertationFilter 。结合使用自定义属性,我能够创建将需要的自定义参数手动添加到Swagger文档的功能。请参阅下面的所有相关代码,请注意 Schema / PartialSchema 具有许多属性,我仅根据需要设置Type,否则可能需要更多属性。

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 (只是摇摇欲坠的操作过滤器部分)

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);