如何更改Swashbuckle中组中列出的操作的顺序?

时间:2017-09-21 08:32:00

标签: c# swagger-ui swashbuckle

我使用Swashbuckle生成Swagger UI。它有选择分组键(默认情况下为控制器)和组排序的选项,但我想选择一个组中操作的顺序,以便GET始终显示在DELETE之前示例

我已经找到了如何实施文档过滤器,我可以通过ApiDescriptions获取HttpMethod订单,但更改ApiDescriptions中的订单并不会反映在swaggerDoc中生成了Swagger UI,我无法找到如何在SwaggerDocument中保留订单。

paths具有PathItem属性,但其中的boolalpha将每个HTTP方法都作为属性,因此我无法确定如何选择演示顺序他们。事实上,当生成我的API的Swagger UI时,不同的控制器会在页面中获得不同的方法顺序。

我应该手动重新排序控制器中的方法实现吗?

4 个答案:

答案 0 :(得分:2)

为了在不拘一格的OpenApi路径json规范中对控制器的操作进行排序,您可以创建一个自定义属性OrderAttribute,然后创建一个IDocumentFilter,它将对OpenApiPaths重新排序。

public class OperationsOrderingFilter : IDocumentFilter
{
    public void Apply(OpenApiDocument openApiDoc, DocumentFilterContext context)
    {
        Dictionary<KeyValuePair<string, OpenApiPathItem>,int> paths = new Dictionary<KeyValuePair<string, OpenApiPathItem>, int>();
        foreach(var path in openApiDoc.Paths)
        {
            OperationOrderAttribute orderAttribute = context.ApiDescriptions.FirstOrDefault(x=>x.RelativePath.Replace("/", string.Empty)
                .Equals( path.Key.Replace("/", string.Empty), StringComparison.InvariantCultureIgnoreCase))?
                .ActionDescriptor?.EndpointMetadata?.FirstOrDefault(x=>x is OperationOrderAttribute) as OperationOrderAttribute;

            if (orderAttribute == null)
                throw new ArgumentNullException("there is no order for operation " + path.Key);

            int order = orderAttribute.Order;
            paths.Add(path, order);
        }

        var orderedPaths = paths.OrderBy(x => x.Value).ToList();
        openApiDoc.Paths.Clear();
        orderedPaths.ForEach(x => openApiDoc.Paths.Add(x.Key.Key, x.Key.Value));
    }

}

则属性为

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class OperationOrderAttribute : Attribute
{
    public int Order { get; }

    public OperationOrderAttribute(int order)
    {
        this.Order = order;
    }
}

过滤器中的标记为

services.AddSwaggerGen(options =>
{
   options.DocumentFilter<OperationsOrderingFilter>();
}

具有该属性的控制器方法的示例为:

[HttpGet]
[OperationOrder(2)]
[Route("api/get")]
public async Task<ActionResult> Get(string model)
{
   ...
}

答案 1 :(得分:1)

你见过这个问题吗? https://github.com/domaindrivendev/Swashbuckle/issues/11

 public class CustomDocumentFilter : IDocumentFilter
 {
     public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, System.Web.Http.Description.IApiExplorer apiExplorer)
     {
         //make operations alphabetic
         var paths = swaggerDoc.paths.OrderBy(e => e.Key).ToList();
         swaggerDoc.paths = paths.ToDictionary(e => e.Key, e => e.Value);


     }
 }

然后:

c.DocumentFilter<CustomDocumentFilter>();

答案 2 :(得分:0)

您必须用自己的版本替换Swashbuckle的index.html,然后在该文件中添加“ operationsSorter”配置参数。这是.NET Core 2.x的步骤。 (.NET框架仅应在VS项目中定义嵌入式资源的方式有所不同。)

  • 从此处获取SwashBuckle原始index.html的副本:https://github.com/domaindrivendev/Swashbuckle.AspNetCore/blob/master/src/Swashbuckle.AspNetCore.SwaggerUI/index.html

  • 将该副本放置在项目的某些子文件夹中。
    您可以选择其他文件名,我选择了: \Resources\Swagger_Custom_index.html

  • 右键单击该文件,选择“属性”,在左窗格中选择“配置属性”,在右窗格中的“高级”下找到条目“ Build Action”并将其设置为“ Embedded resource”。单击确定。

  • 在Startup.cs中添加以下代码段:

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        //...
    
        app.UseSwaggerUI(c =>
        {
            c.IndexStream = () => GetType().GetTypeInfo().Assembly.GetManifestResourceStream("Your.Default.Namespace.Resources.Swagger_Custom_index.html");
        });
    
        app.UseMvc();
    }
    
  • 以上GetManifestResourceStream命令中资源的标识符由以下组成:

    1. 您的默认名称空间(即“ Your.Default.Namespace”)
    2. 资源(即“资源”)的子路径
    3. 资源的文件名(即'Swagger_Custom_index.html')

    所有三个部分都使用点连接(此处没有反斜杠或反斜杠)。
    如果您不使用子路径,但在根目录中有SwashBuckle index.html,则只需省略第2部分。

  • 现在编辑Swagger_Custom_index.html并将此块插入紧靠文件末尾的const ui = SwaggerUIBundle(configObject);行之前:

        // sort end points by verbs ("operations")
        configObject.operationsSorter = (a, b) => {
            var methodsOrder = ["get", "post", "put", "delete", "patch", "options", "trace"];
            var result = methodsOrder.indexOf(a.get("method")) - methodsOrder.indexOf(b.get("method"));
            if (result === 0) {
                result = a.get("path").localeCompare(b.get("path"));
            }
            return result;
        }
    
        // Build a system
        const ui = SwaggerUIBundle(configObject);
    

答案 3 :(得分:0)

遇到了同样的问题,最后设法通过官方文档进行了修复。在此网址https://github.com/domaindrivendev/Swashbuckle.AspNetCore#change-operation-sort-order-eg-for-ui-sorting

上提供
services.AddSwaggerGen(c =>
{
...
c.OrderActionsBy((apiDesc) => $"{apiDesc.ActionDescriptor.RouteValues["controller"]}_{apiDesc.HttpMethod}");
};

这是解决问题的更简单明了的方法:)