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?
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)
{
...
}
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 :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With