简体   繁体   中英

Add `host`, `basePath` and `schemes` to swagger.json using Swashbuckle Aspnetcore

I am using official doc step by step method to configure Swagger UI and generate Swagger JSON file in my ASP.NET core API application.

Get started with Swashbuckle and ASP.NET Core

If I look at my generated swagger.json file - it is missing three important properties host , basePath and schemes

Please help me understand what piece of code can I add so the swagger.json that gets generated will have following mentioned properties/values.

Here is an ideal swagger.json - give attention to the host , basePath and schemes values which are missing if I follow the documentation code in my application

{
  "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": []
    }
  ]
}

There are some changes in latest version of Swashbuckle for .netcore

If you wish to change Request URL in Swashbuckle, maybe you are behind API gateway or have custom domain attached to your webapp. Do this.

  1. Create Document filter
public class BasePathDocumentFilter: IDocumentFilter { public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) { swaggerDoc.Servers = new List<OpenApiServer>() { new OpenApiServer() { Url = "hxxt://yoursite" } }; } }
  1. In your startup file.In services.AddSwaggerGen() method add document filter like this c.DocumentFilter<BasePathDocumentFilter>();

Swagger / open api 3.0 and higher requires the server object. See: https://swagger.io/specification/#server-object

To set it in your startup like this

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

You can implement and register your own IDocumentFilter and set the desired values there.

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" };
    }
}

And then register it via

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

Edit (09SEP20) Here's some code snippets that applies to version 4.xx of the asp.netcore Swashbuckle library

In future I might make another post in case the below is more straightforward with new versions (at time of writing it's at version 5.xx)

sample appsettings.Development.json

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

sample c# code

    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);
            }
        }
    }

I'm using Swashbuckle.AspNetCore Nuget version 4.0.1

I needed to dynamically add the host depending on where the app is hosted.

This was my fix

  1. I your startup.cs add IHttpContextAccessor to your services

  1. In your swagger config, add a DocFilter, like so: 在此处输入图像描述 在此处输入图像描述

So in .net core 3 and Open Api - Nswag.AspNetCore version 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
        };

    });

pulled from this github answer: https://github.com/RicoSuter/NSwag/issues/2441#issuecomment-583721522

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM