使用 Swashbuckle Aspnetcore 将 `host`、`basePath` 和 `schemes` 添加到 swagger.json

Posted

技术标签:

【中文标题】使用 Swashbuckle Aspnetcore 将 `host`、`basePath` 和 `schemes` 添加到 swagger.json【英文标题】:Add `host`, `basePath` and `schemes` to swagger.json using Swashbuckle Aspnetcore 【发布时间】:2019-05-16 13:23:48 【问题描述】:

我正在使用官方文档逐步方法来配置 Swagger UI 并在我的 ASP.NET 核心 API 应用程序中生成 Swagger JSON 文件。

Get started with Swashbuckle and ASP.NET Core

如果我查看生成的 swagger.json 文件 - 它缺少三个重要属性 hostbasePathschemes

请帮助我了解我可以添加哪些代码,以便生成的 swagger.json 将具有以下提到的属性/值。

这是一个理想的 swagger.json - 如果我遵循应用程序中的文档代码,请注意 hostbasePathschemes


  "swagger": "2.0",
  "info": 
    "version": "v1",
    "title": "Demo API Title"
  ,
  "host": "some-url-that-is-hosted-on-azure.azurewebsites.net",
  "basePath": "/api",
  "schemes": ["https"],
  "paths": 
    "/Account/Test": 
      "post": 
        "tags": [
          "Admin"
        ],
        "summary": "Account test method - POST",
        "operationId": "AccountTest",
        "consumes": [],
        "produces": [
          "text/plain",
          "application/json",
          "text/json"
        ],
        "parameters": [],
        "responses": 
          "200": 
            "description": "Success",
            "schema": 
              "type": "boolean"
            
          
        
      
    
  ,
  "definitions": 
    "NumberSearchResult": 
      "type": "object",
      "properties": 
        "number": 
          "type": "string"
        ,
        "location": 
          "type": "string"
        
      
    
  ,
  "securityDefinitions": 
    "Bearer": 
      "name": "Authorization",
      "in": "header",
      "type": "apiKey",
      "description": "Authorization. Example: \"Authorization: Bearer token\""
    
  ,
  "security": [
    
      "Bearer": []
    
  ]

【问题讨论】:

【参考方案1】:

.netcore 的最新版 Swashbuckle 有一些变化

如果您希望更改 Swashbuckle 中的请求 URL,可能您在 API 网关后面或将自定义域附加到您的 web 应用程序。这样做。

    创建文档过滤器
public class BasePathDocumentFilter : IDocumentFilter
    
        public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
        
            swaggerDoc.Servers = new List<OpenApiServer>()  new OpenApiServer()  Url = "hxxt://yoursite"  ;
        
    
    在您的启动文件中。在services.AddSwaggerGen() 方法中添加像这样c.DocumentFilter&lt;BasePathDocumentFilter&gt;(); 的文档过滤器

【讨论】:

谢谢!这对我帮助很大! 如果我想省略host和scheme怎么办?只需更改基本路径【参考方案2】:

您可以实现和注册自己的IDocumentFilter 并在那里设置所需的值。

public class MyDocumentFilter : IDocumentFilter

    public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
    
        swaggerDoc.Host = "some-url-that-is-hosted-on-azure.azurewebsites.net";
        swaggerDoc.BasePath = "/api";
        swaggerDoc.Schemes = new List<string>  "https" ;
    

然后通过

注册
services.AddSwaggerGen(options =>

    options.DocumentFilter<MyDocumentFilter>();
);

【讨论】:

提及:这是针对 V2.x 之前的 OpenAPI【参考方案3】:

Swagger / open api 3.0 及更高版本需要服务器对象。看: https://swagger.io/specification/#server-object

像这样在你的启动中设置它

app.UseSwagger(c =>

    c.PreSerializeFilters.Add((swagger, httpReq) =>
    
        swagger.Servers = new List<OpenApiServer>  new OpenApiServer  Url = $"httpReq.Scheme://httpReq.Host.Value"  ;
    );
);

【讨论】:

【参考方案4】:

编辑 (09SEP20) 下面是一些适用于 4.x.x 版本的 asp.netcore Swashbuckle 库的代码 sn-ps

将来我可能会再发一篇文章,以防下面的新版本更简单(在撰写本文时它是版本 5.x.x)

示例 appsettings.Development.json


  "Logging": 
    "LogLevel": 
      "Default": "Warning",
      "Microsoft.Hosting.*": "Information"
    
  ,
  "Swagger": 
    "ApiVersion": "localhost",
    "ApiName": "v1",
    "SwaggerRelativeUrl": "/swagger/v1/swagger.json",
    "Title": "SalesforceLocationApi"
  

示例 C# 代码

    namespace My.Api.Settings
    
        public class SwaggerSettings
        
            public string? ApiName  get; set; 
            public string? ApiVersion  get; set; 
            public string? SwaggerRelativeUrl  get; set; 
            public string? Title  get; set; 
        
    


    using Microsoft.AspNetCore.Authentication;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Diagnostics;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Http.Extensions;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Hosting;
    using Microsoft.Extensions.Logging;
    using Newtonsoft.Json;
    using Swashbuckle.AspNetCore.SwaggerGen;
    using Swashbuckle.AspNetCore.SwaggerUI;
    using System;
    using System.Reflection;
    
    namespace My.Api
    
        public class Startup
        
            private readonly IConfiguration _configuration;
    
            public Startup(IConfiguration configuration)
            
                _configuration = configuration;
            
    
            public void ConfigureServices(IServiceCollection services)
            
                services.AddControllers(ConfigureControllers);
    
                services
                    .AddSingleton<IHttpContextAccessor, HttpContextAccessor>()
                    .AddSwaggerGen(SetupUpSwaggerGen);
            
    
            public void Configure(IApplicationBuilder application, IWebHostEnvironment environment, ILoggerFactory loggerFactory, IMapper mapper)
            
                if (environment.IsDevelopment())
                
                    application.UseDeveloperExceptionPage();
                
                else
                
                    application.UseExceptionHandler();
                
    
                application
                    .UseHttpsRedirection()
                    .UseSwagger()
                    .UseSwaggerUI(SetUpSwaggerUi)
                    .UseRouting()
                    .UseAuthorization()
                    .UseEndpoints(endpoints => endpoints.MapControllers());
            
    
            #region Helpers
    
            private void SetupUpSwaggerGen(SwaggerGenOptions options)
            
                var swaggerSettings = _configuration.GetSection("Swagger").Get<SwaggerSettings>();
                SwaggerConfig.SetUpSwaggerGen(options, swaggerSettings);
            
    
            private void SetUpSwaggerUi(SwaggerUIOptions options)
            
                var swaggerSettings = _configuration.GetSection("Swagger").Get<SwaggerSettings>();
                SwaggerConfig.SetUpSwaggerUi(options, swaggerSettings.SwaggerRelativeUrl, swaggerSettings.ApiName);
            
    
            #endregion
        
    

    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Http;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.OpenApi.Models;
    using Swashbuckle.AspNetCore.SwaggerGen;
    using Swashbuckle.AspNetCore.SwaggerUI;
    using System;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    
    namespace My.Api
    
        public class SwaggerConfig
        
            internal class SwaggerDocumentFilter : IDocumentFilter
            
                private readonly string _swaggerDocHost;
    
                public SwaggerDocumentFilter(IHttpContextAccessor httpContextAccessor)
                
                    var host = httpContextAccessor.HttpContext.Request.Host.Value;
                    var scheme = httpContextAccessor.HttpContext.Request.Scheme;
                    _swaggerDocHost = $"scheme://host";
                
    
                public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
                
                    swaggerDoc.Servers.Add(new OpenApiServer  Url = _swaggerDocHost );
                
            
    
            internal static void SetUpSwaggerGen(SwaggerGenOptions options, SwaggerSettings swaggerSettings)
            
                options.DocumentFilter<SwaggerDocumentFilter>();
                options.SwaggerDoc(swaggerSettings.ApiName, new OpenApiInfo  Title = swaggerSettings.Title, Version = swaggerSettings.ApiVersion );
                options.CustomSchemaIds(type => $"type?.Namespace?.Split('.').Last().type?.Name"); //E.g. Acme.Dtos.Gas.Meter.cs --> Gas.Meter
    
                AddXmlComments(options);
            
    
            internal static void SetUpSwaggerUi(SwaggerUIOptions options, string? swaggerRelativeUrl, string? apiName)
            
                options.SwaggerEndpoint(swaggerRelativeUrl, apiName);
            
    
            private static void AddXmlComments(SwaggerGenOptions options)
            
                var xmlFile = $"Assembly.GetExecutingAssembly().GetName().Name.xml";
                var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
                options.IncludeXmlComments(xmlPath);
            
        
    

我正在使用 Swashbuckle.AspNetCore Nuget 4.0.1 版

我需要根据应用的托管位置动态添加主机。

这是我的解决方法

    你的 startup.cs 将 IHttpContextAccessor 添加到你的服务中

    在您的 swagger 配置中,添加一个 DocFilter,如下所示:

【讨论】:

这对我来说就像一个魅力的解决方案......感谢您发布此答案。我也在使用 4.0.1 版本。 如果你也分享代码而不仅仅是截图会很酷。【参考方案5】:

所以在 .net core 3 和 Open Api - Nswag.AspNetCore 版本 13.3.2 nuget。

    app.UseOpenApi( configure =>  
        configure.PostProcess = (doc, httpReq) =>
        
            doc.Servers.Clear(); //... remove local host, added via asp .net core
            doc.Servers.Add(new OpenApiServer  Url = "[YOUR SERVER URL]" );  //... add server
        ;

    );

来自这个 github 答案:https://github.com/RicoSuter/NSwag/issues/2441#issuecomment-583721522

【讨论】:

以上是关于使用 Swashbuckle Aspnetcore 将 `host`、`basePath` 和 `schemes` 添加到 swagger.json的主要内容,如果未能解决你的问题,请参考以下文章

Swashbuckle.AspNetCore3.0的二次封装与使用

使用Swashbuckle.AspNetCore生成.NetCore WEBAPI的接口文档

TS6053 构建 Swashbuckle.AspNetCore

Swashbuckle.AspNetCore.SwaggerGen 版本 5.6.X 没有 IDataContractResolver

如何使用 Swashbuckle.AspNetCore 在 Swagger 模式中将自定义泛型类型公开为字符串

Azure Functions Swashbuckle:在重建期间无法解析程序集“Microsoft.AspNetCore.Mvc.Core”