How can I change order the operations are listed in a group in Swashbuckle?

14,560

Solution 1

Have you seen this issue? 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);
     }
 }

and then:

c.DocumentFilter<CustomDocumentFilter>();

Solution 2

Had the same issue, and finally managed to fix it with the official doc. provided on this URL 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}");
};

Is an easier and clearer path to solve it :)

Solution 3

In order to order the Operations of controller in swagger OpenApi paths json spec you could create a custom Attribute OrderAttribute and then a IDocumentFilter which will reorder the 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));
    }

}

then the attribute would be

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

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

the registration of the filter in swagger would be

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

and an example of a controller method with the attribute would be:

[HttpGet]
[OperationOrder(2)]
[Route("api/get")]
public async Task<ActionResult> Get(string model)
{
   ...
}
Share:
14,560
lpacheco
Author by

lpacheco

SOreadytohelp

Updated on June 14, 2022

Comments

  • lpacheco
    lpacheco almost 2 years

    I'm using Swashbuckle to generate Swagger UI. It has options for choosing a grouping key (controller by default) and the ordering of the groups, but I would like to choose an order for the operations in a group so that GET appears always before DELETE for example.

    I've found how to implement document filters and I can get and order ApiDescriptions by HttpMethod, but changing the order in ApiDescriptions doesn't reflect in the generated Swagger UI and I can't find how to persist the order in swaggerDoc.

    SwaggerDocument has a paths property, but the PathItem in it has each HTTP method as a property, so I can't figure how to choose an order of presentation for them. Eventough, when the Swagger UI for my API is generated, different controllers get different method order in the page.

    Should I manually reorder the methods implementation in my controller instead?