NSwag 多文档端点

标签 nswag

是否可以像 swashbuckle 那样拥有多个文档端点?

options.SwaggerEndpoint("/swagger/v1/swagger.json", "API v1");
options.SwaggerEndpoint("/swagger/v2/swagger.json", "API v2");

如果是,如何修饰 api 调用,使一些属于一个版本,一些属于另一个版本?

所以根据 Rico Suter 的建议,我所做的有点像那样:

ApiVersionAttribute.cs

public class ApiVersionAttribute:Attribute
    {
        private List<string> _versions = new List<string>();

        public List<string> Versions { get { return _versions; } }

        public ApiVersionAttribute(string version) {
            Versions.Add(version);
        }
    }

MyApiVersionProcessor.cs

        public string Version { get; set; }

        public MyApiVersionProcessor(string version)
        {
            this.Version = version;
        }

        public new Task<bool> ProcessAsync(OperationProcessorContext context)
        {
            bool returnValue = true;

            var versionAttributes = context.MethodInfo.GetCustomAttributes()
                .Concat(context.MethodInfo.DeclaringType.GetTypeInfo().GetCustomAttributes())
                .Where(a => a.GetType()
                                .IsAssignableTo("MapToApiVersionAttribute", TypeNameStyle.Name) 
                            || a.GetType()
                                .IsAssignableTo("ApiVersionAttribute", TypeNameStyle.Name)
                       )
                .Select(a => (dynamic)a)
                .ToArray();

            var versionAttribute = versionAttributes.FirstOrDefault();

            if (null == versionAttribute)
            {
                returnValue = false;
            }
            else
            {
                if (ObjectExtensions.HasProperty(versionAttribute, "Versions")
                    && Version.Equals(versionAttribute.Versions[0].ToString()))
                {
                    ReplaceApiVersionInPath(context.OperationDescription, versionAttribute.Versions);
                }
                else {
                    returnValue = false;
                }
            }

            return Task.FromResult(returnValue);
        }

        private void ReplaceApiVersionInPath(SwaggerOperationDescription operationDescription,
            dynamic versions)
        {
            operationDescription.Path = operationDescription.Path.Replace("{version:apiVersion}",
                versions[0].ToString());
        }
    }

在我的 Global.asax 中

                // NSwag
                // https://github.com/RSuter/NSwag/wiki/OwinGlobalAsax#integration                
                app.UseSwaggerUi(typeof(WebApiApplication).Assembly, new SwaggerUiSettings
                {                       
                    //TypeNameGenerator = new MyTypeNameGenerator(),
                    MiddlewareBasePath = "/swagger",
                    SwaggerRoute = "/swagger/v1/swagger.json",
                    Version = "1.0.0.0",
                    // https://github.com/RSuter/NSwag/wiki/Middlewares
                    OperationProcessors =
                    {
                        new MyApiVersionProcessor("v1")
                    },
                    PostProcess = document =>
                    {                        
                        document.BasePath = "/";
                        document.Produces
                            = new List<string> { "application/json"
                                                , "text/json"
                                                , "text/html"
                                                , "plain/text"
                                                , "application/xml"};
                        document.Consumes
                            = document.Produces;
                        document.Info.Title = "Document V1";                     
                    }

                });

                app.UseSwaggerUi(typeof(WebApiApplication).Assembly, new SwaggerUiSettings
                {
                    //TypeNameGenerator = new MyTypeNameGenerator(),
                    MiddlewareBasePath = "/swagger",
                    SwaggerRoute = "/swagger/v2/swagger.json",
                    Version = "2.0.0.0",
                    OperationProcessors =
                    {
                        new MyApiVersionProcessor("v2")
                    },
                    PostProcess = document =>
                    {
                        document.BasePath = "/";
                        document.Produces
                            = new List<string> { "application/json"
                                                , "text/json"
                                                , "text/html"};
                        document.Consumes
                            = document.Produces;
                        document.Info.Title = "Document V2";
                    }

                });

并用

装饰我的 Controller 方法
[ApiVersion("v2")]

[ApiVersion("v1")]

等等

最佳答案

您可以定义 app.UseSwagger 两次并实现一个自定义操作处理器,该处理器根据您的需要仅过滤所需的 api 操作(即在第一次调用中您应该过滤所有版本 x,在第二次调用中过滤所有y 的版本)。

目前默认添加的ApiVersionProcessor只会将路由路径中的版本占位符替换为第一个声明的版本。我认为我们应该扩展此处理器,以便您可以排除版本并插入正确的版本。

顺便说一句:我是 NSwag 的作者。

关于NSwag 多文档端点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45238908/

相关文章:

c# - 尝试访问 swagger 端点时,将 Nswag 与 Odata 结合使用会产生错误

swagger - 将 JWT Bearer Auth 添加到 OpenAPI3 NSwag 生成的客户端

openapi - NSwag 使用 OpenApi 3.0 JSON 文件时生成多个同名函数

c# - 如何更改由 nswag 生成的默认信息标题?

NSwag 生成重复类型

C#NSwag和带有Enums的swagger-codegen

c# - swashbuckle cli 和 .net 中的 nswag 中的可为空引用类型

.net - 如何调用请求 header 上需要不记名 token 的 NSwag 客户端方法?

c# - NSwag 的 AspNetCoreOperationSecurityScopeProcessor 将所有端点标记为需要授权

c# - NSwag:如何在 C# -> Swagger -> C# 客户端中使用自定义值对象类型?