使用 Swashbuckle Aspnetcore 将 `host`、`basePath` 和 `schemes` 添加到 swagger.json
Add `host`, `basePath` and `schemes` to swagger.json using Swashbuckle Aspnetcore
我正在使用官方文档逐步配置 Swagger UI 并在我的 ASP.NET 核心 API 应用程序中生成 Swagger JSON 文件。
Get started with Swashbuckle and ASP.NET Core
如果我查看生成的 swagger.json 文件 - 它缺少三个重要属性 host
、basePath
和 schemes
请帮助我了解我可以添加哪些代码,以便生成的 swagger.json 将包含以下提到的 properties/values。
这是一个理想的 swagger.json - 请注意 host
、basePath
和 schemes
值,如果我遵循我的应用程序中的文档代码,这些值会丢失
{
"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": []
}
]
}
您可以实施和注册自己的 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>();
});
最新版本的 Swashbuckle for .netcore 有一些变化
如果您希望在 Swashbuckle 中更改请求 URL,可能您在 API 网关后面或者您的 webapp 附加了自定义域。这样做。
- 创建文档过滤器
public class BasePathDocumentFilter : IDocumentFilter
{
public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
{
swaggerDoc.Servers = new List<OpenApiServer>() { new OpenApiServer() { Url = "hxxt://yoursite" } };
}
}
- 在您的启动 file.In
services.AddSwaggerGen()
方法中添加这样的文档过滤器 c.DocumentFilter<BasePathDocumentFilter>();
编辑 (09SEP20)
以下是适用于 asp.netcore Swashbuckle 库
版本 4.x.x 的一些代码片段
将来我可能会制作另一个 post 以防下面的新版本更直接(在撰写本文时它的版本为 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,如下所示:
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}" } };
});
});
所以在 .net core 3 中打开 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
我正在使用官方文档逐步配置 Swagger UI 并在我的 ASP.NET 核心 API 应用程序中生成 Swagger JSON 文件。
Get started with Swashbuckle and ASP.NET Core
如果我查看生成的 swagger.json 文件 - 它缺少三个重要属性 host
、basePath
和 schemes
请帮助我了解我可以添加哪些代码,以便生成的 swagger.json 将包含以下提到的 properties/values。
这是一个理想的 swagger.json - 请注意 host
、basePath
和 schemes
值,如果我遵循我的应用程序中的文档代码,这些值会丢失
{
"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": []
}
]
}
您可以实施和注册自己的 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>();
});
最新版本的 Swashbuckle for .netcore 有一些变化
如果您希望在 Swashbuckle 中更改请求 URL,可能您在 API 网关后面或者您的 webapp 附加了自定义域。这样做。
- 创建文档过滤器
public class BasePathDocumentFilter : IDocumentFilter { public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) { swaggerDoc.Servers = new List<OpenApiServer>() { new OpenApiServer() { Url = "hxxt://yoursite" } }; } }
- 在您的启动 file.In
services.AddSwaggerGen()
方法中添加这样的文档过滤器c.DocumentFilter<BasePathDocumentFilter>();
编辑 (09SEP20) 以下是适用于 asp.netcore Swashbuckle 库
版本 4.x.x 的一些代码片段将来我可能会制作另一个 post 以防下面的新版本更直接(在撰写本文时它的版本为 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,如下所示:
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}" } };
});
});
所以在 .net core 3 中打开 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