我使用Swashbuckle生成Swagger UI。它有选择分组键(默认情况下为控制器)和组排序的选项,但我想选择一个组中操作的顺序,以便GET
始终显示在DELETE
之前示例
我已经找到了如何实施文档过滤器,我可以通过ApiDescriptions
获取HttpMethod
订单,但更改ApiDescriptions
中的订单并不会反映在swaggerDoc
中生成了Swagger UI,我无法找到如何在SwaggerDocument
中保留订单。
paths
具有PathItem
属性,但其中的boolalpha
将每个HTTP方法都作为属性,因此我无法确定如何选择演示顺序他们。事实上,当生成我的API的Swagger UI时,不同的控制器会在页面中获得不同的方法顺序。
我应该手动重新排序控制器中的方法实现吗?
答案 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
命令中资源的标识符由以下组成:
所有三个部分都使用点连接(此处没有反斜杠或反斜杠)。
如果您不使用子路径,但在根目录中有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}");
};
这是解决问题的更简单明了的方法:)