【问题标题】:Adding Query String Params to my Swagger Specs将查询字符串参数添加到我的 Swagger Specs
【发布时间】:2016-03-06 14:52:32
【问题描述】:

我在我的 Web API 中使用 Swashbuckle(C# 的招摇)。我有几个返回列表的 GET 端点,我允许用户将 perpage 和 page params 添加到 QueryString

示例:http://myapi.com/endpoint/?page=5&perpage=10

我看到 swagger 确实支持“查询”中的参数,但我如何让 Swashbuckle 做到这一点?


我在其中一个 cmets 中提到,我通过创建自定义属性来解决我的问题,以允许我做我需要的事情。以下是我的解决方案的代码:

[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = true)]
public class SwaggerParameterAttribute : Attribute
{
    public SwaggerParameterAttribute(string name, string description)
    {
        Name = name;
        Description = description;
    }

    public string Name { get; private set; }
    public Type DataType { get; set; }
    public string ParameterType { get; set; }
    public string Description { get; private set; }
    public bool Required { get; set; } = false;
}

使用 Swagger Config 注册属性:

GlobalConfiguration.Configuration 
    .EnableSwagger(c =>
        {
            c.OperationFilter<SwaggerParametersAttributeHandler>();
        });

然后将此属性添加到您的方法中:

[SwaggerParameter("page", "Page number to display", DataType = typeof(Int32), ParameterType = ParameterType.inQuery)]
[SwaggerParameter("perpage","Items to display per page", DataType = typeof(Int32), ParameterType = ParameterType.inQuery)]

【问题讨论】:

  • SwaggerParametersAttributeHandler 来自哪里? :s
  • 该死,显然ParameterType 枚举也丢失了。你愿意为我们填空吗? :D

标签: c# swagger swashbuckle


【解决方案1】:

你可以很容易地做到这一点。假设您有一个 ItemsController ,其操作如下:

[Route("/api/items/{id}")]
public IHttpActionResult Get(int id, int? page = null, int? perpage = null)
{
   // some relevant code
   return Ok();
}

Swashbuckle 将生成此规范(仅显示相关部分):

"paths":{  
  "/api/items/{id}":{  
     "get":{  
        "parameters":[  
           {  
              "name":"id",
              "in":"path",
              "required":true,
              "type":"integer",
              "format":"int32"
           },
           {  
              "name":"page",
              "in":"query",
              "required":false,
              "type":"integer",
              "format":"int32"
           },
           {  
              "name":"limit",
              "in":"query",
              "required":false,
              "type":"integer",
              "format":"int32"
           }
        ]
     }
  }

当您希望pageperpage 成为必需时,只需使参数不可为空即可。

【讨论】:

  • 这是一个非常合理的答案,但我最终创建了一个自定义 Swagger 属性来处理它
  • 你是如何做到的@JasonH?在线资源是否可以指向您提到的解决方案?
  • 我正在处理的代码不属于我自己,所以我没有分享我创建的属性。我可以用我所做的来编辑我的原始问题,以便您看到。
  • 谢谢@JasonH。您给出的示例中是否缺少某些内容? swagger 怎么知道如何解析你创建的这个属性?
  • 对不起,你是对的,我忘记了一个重要的部分。您必须使用 Swagger 配置注册该属性。我已经编辑了我的原始帖子以显示这一点。
【解决方案2】:

这里总结了 Attribute 方法所需的步骤(ASP.Net Core 2.1、Swashbuckle.AspNetCore v4.0.1)。我需要一个以“$”开头的参数,所以可选参数不是一个选项!

SwaggerParameterAttribute.cs

     [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = true)]
     public class SwaggerParameterAttribute : Attribute
     {
         public SwaggerParameterAttribute(string name, string description)
        {
            Name = name;
            Description = description;
        }

        public string Name { get; private set; }
        public string DataType { get; set; }
        public string ParameterType { get; set; }
        public string Description { get; private set; }
        public bool Required { get; set; } = false;
    }

SwaggerParameterAttributeFilter.cs

using Swashbuckle.AspNetCore.Swagger;
using Swashbuckle.AspNetCore.SwaggerGen;
using System.Linq;
public class SwaggerParameterAttributeFilter : IOperationFilter
{
    public void Apply(Operation operation, OperationFilterContext context)
    {
        var attributes = context.MethodInfo.DeclaringType.GetCustomAttributes(true)
            .Union(context.MethodInfo.GetCustomAttributes(true))
            .OfType<SwaggerParameterAttribute>();

        foreach (var attribute in attributes)
            operation.Parameters.Add(new NonBodyParameter
            {
                Name = attribute.Name,
                Description = attribute.Description,
                In = attribute.ParameterType,
                Required = attribute.Required,
                Type = attribute.DataType
            });              
    }
}

在 Startup.ConfigureServices 中添加它

 using Swashbuckle.AspNetCore.Swagger;
 services.AddSwaggerGen(c =>
 {
      c.OperationFilter<SwaggerParameterAttributeFilter>();
      c.SwaggerDoc("v1.0", new Info { Title = "My API", Version = "v1.0" });
 });

并像这样使用:

[SwaggerParameter("$top", "Odata Top parameter", DataType = "integer", ParameterType ="query")]

数据类型可以是:整数、字符串、布尔值

ParameterTypes:可以是路径、正文、查询

【讨论】:

    【解决方案3】:

    这里有一些关于 SwaggerParametersAttributeHandler 缺少信息的 cmets。它是一个操作过滤器,可帮助您确定如何处理您的属性。

    这是我使用的示例处理程序,它允许我使用 SwaggerParameterAttribute 覆盖可为空参数的必填字段。

    public class RequiredParameterOverrideOperationFilter : IOperationFilter
    {
        public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
        {
            // Get all SwaggerParameterAttributes on the method
            var attributes = apiDescription.ActionDescriptor.GetCustomAttributes<SwaggerParameterAttribute>();
    
            if (operation.parameters == null)
            {
                operation.parameters = new List<Parameter>();
            }
    
            // For each attribute found, find the operation parameter (this is where Swagger looks to generate the Swagger doc)
            // Override the required fields based on the attribute's required field
            foreach (var attribute in attributes)
            {
                var referencingOperationParameter = operation.parameters.FirstOrDefault(p => p.name == attribute.Name);
    
                if (referencingOperationParameter != null)
                {
                    referencingOperationParameter.required = attribute.Required;
                }
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2011-02-11
      • 2012-05-31
      • 1970-01-01
      • 1970-01-01
      • 2014-06-15
      • 2019-09-20
      • 2015-05-20
      • 2022-10-25
      • 1970-01-01
      相关资源
      最近更新 更多