├── tools ├── clear.bat ├── nuget.exe ├── pack.bat ├── pack.Magicodes.SwaggerUI.bat └── .vscode │ └── launch.json ├── res ├── 1.png ├── 2.png ├── 3.png └── wechat.jpg ├── src ├── TestHost3.1 │ ├── Startup.cs │ ├── appsettings.Development.json │ ├── WeatherForecast.cs │ ├── Controllers │ │ ├── HomeController.cs │ │ ├── ValuesController.cs │ │ └── WeatherForecastController.cs │ ├── TestHost3.1.csproj │ ├── appsettings.json │ ├── Program.cs │ └── Properties │ │ └── launchSettings.json ├── TestHost │ ├── appsettings.Development.json │ ├── Controllers │ │ ├── HomeController.cs │ │ └── ValuesController.cs │ ├── TestHost.csproj │ ├── appsettings.json │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ └── Startup.cs ├── ApiGroupTestHost │ ├── appsettings.Development.json │ ├── Controllers │ │ ├── HomeController.cs │ │ ├── App1Controller.cs │ │ └── App2Controller.cs │ ├── ApiGroupTestHost.csproj │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── appsettings.json │ └── Startup.cs ├── Magicodes.SwaggerUI │ ├── Models │ │ ├── ContactInfo.cs │ │ ├── HiddenApiConfigInfo.cs │ │ ├── ApiConfigInfo.cs │ │ ├── SwaggerConfigInfo.cs │ │ └── SwaggerDocInfo.cs │ ├── SwaggerOperationFilter.cs │ ├── SwaggerEnumSchemaFilter.cs │ ├── SwaggerOperationIdFilter.cs │ ├── Magicodes.SwaggerUI.csproj │ ├── SwaggerEnumParameterFilter.cs │ ├── DictionaryExtensions.cs │ └── Extentions.cs └── Magicodes.SwaggerUI.sln ├── .gitattributes ├── .gitignore └── README.md /tools/clear.bat: -------------------------------------------------------------------------------- 1 | cd ./nupkgs/ 2 | del *.nupkg /f /q /a 3 | cd ../ -------------------------------------------------------------------------------- /res/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xin-lai/Magicodes.SwaggerUI/HEAD/res/1.png -------------------------------------------------------------------------------- /res/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xin-lai/Magicodes.SwaggerUI/HEAD/res/2.png -------------------------------------------------------------------------------- /res/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xin-lai/Magicodes.SwaggerUI/HEAD/res/3.png -------------------------------------------------------------------------------- /res/wechat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xin-lai/Magicodes.SwaggerUI/HEAD/res/wechat.jpg -------------------------------------------------------------------------------- /tools/nuget.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xin-lai/Magicodes.SwaggerUI/HEAD/tools/nuget.exe -------------------------------------------------------------------------------- /tools/pack.bat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xin-lai/Magicodes.SwaggerUI/HEAD/tools/pack.bat -------------------------------------------------------------------------------- /src/TestHost3.1/Startup.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xin-lai/Magicodes.SwaggerUI/HEAD/src/TestHost3.1/Startup.cs -------------------------------------------------------------------------------- /tools/pack.Magicodes.SwaggerUI.bat: -------------------------------------------------------------------------------- 1 | call ./clear.bat 2 | call ./pack.bat "Magicodes.SwaggerUI.*.nupkg" "../src/Magicodes.SwaggerUI/Magicodes.SwaggerUI.csproj" 3 | @pause -------------------------------------------------------------------------------- /src/TestHost/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/ApiGroupTestHost/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/TestHost3.1/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/TestHost3.1/WeatherForecast.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace TestHost3._1 4 | { 5 | public class WeatherForecast 6 | { 7 | public DateTime Date { get; set; } 8 | 9 | public int TemperatureC { get; set; } 10 | 11 | public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); 12 | 13 | public string Summary { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/TestHost/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | 7 | namespace TestHost.Controllers 8 | { 9 | public class HomeController: ControllerBase 10 | { 11 | public IActionResult Index() 12 | { 13 | return Redirect("/swagger"); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/TestHost3.1/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | 7 | namespace TestHost3._1.Controllers 8 | { 9 | public class HomeController: ControllerBase 10 | { 11 | public IActionResult Index() 12 | { 13 | return Redirect("/swagger"); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/ApiGroupTestHost/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | 7 | namespace ApiGroupTestHost.Controllers 8 | { 9 | public class HomeController: ControllerBase 10 | { 11 | public IActionResult Index() 12 | { 13 | return Redirect("/swagger"); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/TestHost3.1/TestHost3.1.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | TestHost3._1 6 | bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/TestHost/TestHost.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.2 5 | InProcess 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/TestHost/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Warning" 5 | } 6 | }, 7 | "SwaggerDoc": { 8 | "IsEnabled": "true", 9 | //将枚举值以字符串显示 10 | "DescribeAllEnumsAsStrings": false, 11 | "SwaggerDocInfos": [ 12 | { 13 | "IsEnabled": "true", 14 | "Title": "APP API文档", 15 | "Version": "v1", 16 | //"GroupName": "", 17 | "Description": "", 18 | "Contact": { 19 | "Name": "心莱科技", 20 | "Email": "xinlai@xin-lai.com" 21 | }, 22 | //"GroupUrlPrefix": "api/app1/" 23 | } 24 | ], 25 | "UseFullNameForSchemaId": "false" 26 | }, 27 | "AllowedHosts": "*" 28 | } 29 | -------------------------------------------------------------------------------- /src/TestHost3.1/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Warning" 5 | } 6 | }, 7 | "SwaggerDoc": { 8 | "IsEnabled": "true", 9 | //将枚举值以字符串显示 10 | "DescribeAllEnumsAsStrings": false, 11 | "SwaggerDocInfos": [ 12 | { 13 | "IsEnabled": "true", 14 | "Title": "APP API文档", 15 | "Version": "v1", 16 | //"GroupName": "", 17 | "Description": "", 18 | "Contact": { 19 | "Name": "心莱科技", 20 | "Email": "xinlai@xin-lai.com" 21 | } 22 | //"GroupUrlPrefix": "api/app1/" 23 | } 24 | ], 25 | "UseFullNameForSchemaId": "false" 26 | }, 27 | "AllowedHosts": "*" 28 | } 29 | -------------------------------------------------------------------------------- /src/TestHost/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.Logging; 10 | 11 | namespace TestHost 12 | { 13 | public class Program 14 | { 15 | public static void Main(string[] args) 16 | { 17 | CreateWebHostBuilder(args).Build().Run(); 18 | } 19 | 20 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) => 21 | WebHost.CreateDefaultBuilder(args) 22 | .UseStartup(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/ApiGroupTestHost/ApiGroupTestHost.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.2 5 | InProcess 6 | bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/ApiGroupTestHost/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.Logging; 10 | 11 | namespace ApiGroupTestHost 12 | { 13 | public class Program 14 | { 15 | public static void Main(string[] args) 16 | { 17 | CreateWebHostBuilder(args).Build().Run(); 18 | } 19 | 20 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) => 21 | WebHost.CreateDefaultBuilder(args) 22 | .UseStartup(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/TestHost3.1/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.Extensions.Configuration; 7 | using Microsoft.Extensions.Hosting; 8 | using Microsoft.Extensions.Logging; 9 | 10 | namespace TestHost3._1 11 | { 12 | public class Program 13 | { 14 | public static void Main(string[] args) 15 | { 16 | CreateHostBuilder(args).Build().Run(); 17 | } 18 | 19 | public static IHostBuilder CreateHostBuilder(string[] args) => 20 | Host.CreateDefaultBuilder(args) 21 | .ConfigureWebHostDefaults(webBuilder => 22 | { 23 | webBuilder.UseStartup(); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Magicodes.SwaggerUI/Models/ContactInfo.cs: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // 3 | // Copyright (C) 2019-2030 湖南心莱信息科技有限公司 4 | // All rights reserved 5 | // 6 | // filename : ContactInfo.cs 7 | // description : 8 | // 9 | // created by 雪雁 at -- 10 | // 文档官网:https://docs.xin-lai.com 11 | // 公众号教程:麦扣聊技术 12 | // QQ群:85318032(编程交流) 13 | // Blog:http://www.cnblogs.com/codelove/ 14 | // 15 | // ====================================================================== 16 | 17 | namespace Magicodes.SwaggerUI.Models 18 | { 19 | /// 20 | /// 联系信息 21 | /// 22 | public class ContactInfo 23 | { 24 | public string Name { get; set; } 25 | public string Email { get; set; } 26 | } 27 | } -------------------------------------------------------------------------------- /src/TestHost/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:13976", 8 | "sslPort": 0 9 | } 10 | }, 11 | "profiles": { 12 | "IIS Express": { 13 | "commandName": "IISExpress", 14 | "launchBrowser": true, 15 | "launchUrl": "", 16 | "environmentVariables": { 17 | "ASPNETCORE_ENVIRONMENT": "Development" 18 | } 19 | }, 20 | "TestHost": { 21 | "commandName": "Project", 22 | "launchBrowser": true, 23 | "launchUrl": "", 24 | "applicationUrl": "http://localhost:5000", 25 | "environmentVariables": { 26 | "ASPNETCORE_ENVIRONMENT": "Development" 27 | } 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/ApiGroupTestHost/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:31901", 8 | "sslPort": 0 9 | } 10 | }, 11 | "profiles": { 12 | "IIS Express": { 13 | "commandName": "IISExpress", 14 | "launchBrowser": true, 15 | "launchUrl": "", 16 | "environmentVariables": { 17 | "ASPNETCORE_ENVIRONMENT": "Development" 18 | } 19 | }, 20 | "ApiGroupTestHost": { 21 | "commandName": "Project", 22 | "launchBrowser": true, 23 | "launchUrl": "", 24 | "applicationUrl": "http://localhost:5000", 25 | "environmentVariables": { 26 | "ASPNETCORE_ENVIRONMENT": "Development" 27 | } 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/TestHost3.1/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:43828", 8 | "sslPort": 0 9 | } 10 | }, 11 | "profiles": { 12 | "IIS Express": { 13 | "commandName": "IISExpress", 14 | "launchBrowser": true, 15 | "launchUrl": "swagger/", 16 | "environmentVariables": { 17 | "ASPNETCORE_ENVIRONMENT": "Development" 18 | } 19 | }, 20 | "TestHost3._1": { 21 | "commandName": "Project", 22 | "launchBrowser": true, 23 | "launchUrl": "swagger/", 24 | "applicationUrl": "http://localhost:5000", 25 | "environmentVariables": { 26 | "ASPNETCORE_ENVIRONMENT": "Development" 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Magicodes.SwaggerUI/Models/HiddenApiConfigInfo.cs: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // 3 | // Copyright (C) 2019-2030 湖南心莱信息科技有限公司 4 | // All rights reserved 5 | // 6 | // filename : HiddenApiConfig.cs 7 | // description : 8 | // 9 | // created by 雪雁 at -- 10 | // 文档官网:https://docs.xin-lai.com 11 | // 公众号教程:麦扣聊技术 12 | // QQ群:85318032(编程交流) 13 | // Blog:http://www.cnblogs.com/codelove/ 14 | // 15 | // ====================================================================== 16 | 17 | using System.Collections.Generic; 18 | 19 | namespace Magicodes.SwaggerUI.Models 20 | { 21 | /// 22 | /// API隐藏配置 23 | /// 24 | public class HiddenApiConfigInfo 25 | { 26 | public bool IsEnabled { get; set; } 27 | 28 | /// 29 | /// 30 | /// 31 | public List Urls { get; set; } 32 | } 33 | } -------------------------------------------------------------------------------- /src/Magicodes.SwaggerUI/Models/ApiConfigInfo.cs: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // 3 | // Copyright (C) 2019-2030 湖南心莱信息科技有限公司 4 | // All rights reserved 5 | // 6 | // filename : HiddenApiConfig.cs 7 | // description : 8 | // 9 | // created by 雪雁 at -- 10 | // 文档官网:https://docs.xin-lai.com 11 | // 公众号教程:麦扣聊技术 12 | // QQ群:85318032(编程交流) 13 | // Blog:http://www.cnblogs.com/codelove/ 14 | // 15 | // ====================================================================== 16 | 17 | namespace Magicodes.SwaggerUI.Models 18 | { 19 | /// 20 | /// API配置 21 | /// 22 | public class ApiConfigInfo 23 | { 24 | /// 25 | /// 支持部分路径匹配 26 | /// 27 | public string Url { get; set; } 28 | 29 | /// 30 | /// HTTP方法配置(Get、Post),默认“*” 31 | /// 32 | public string HttpMethod { get; set; } = "*"; 33 | } 34 | } -------------------------------------------------------------------------------- /src/TestHost/Controllers/ValuesController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | 7 | namespace TestHost.Controllers 8 | { 9 | [Route("api/[controller]")] 10 | [ApiController] 11 | public class ValuesController : ControllerBase 12 | { 13 | // GET api/values 14 | [HttpGet] 15 | public ActionResult> Get() 16 | { 17 | return new string[] { "value1", "value2" }; 18 | } 19 | 20 | // GET api/values/5 21 | [HttpGet("{id}")] 22 | public ActionResult Get(int id) 23 | { 24 | return "value"; 25 | } 26 | 27 | // POST api/values 28 | [HttpPost] 29 | public void Post([FromBody] string value) 30 | { 31 | } 32 | 33 | // PUT api/values/5 34 | [HttpPut("{id}")] 35 | public void Put(int id, [FromBody] string value) 36 | { 37 | } 38 | 39 | // DELETE api/values/5 40 | [HttpDelete("{id}")] 41 | public void Delete(int id) 42 | { 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/TestHost3.1/Controllers/ValuesController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | 7 | namespace TestHost3._1.Controllers 8 | { 9 | [Route("api/[controller]")] 10 | [ApiController] 11 | public class ValuesController : ControllerBase 12 | { 13 | // GET api/values 14 | [HttpGet] 15 | public ActionResult> Get() 16 | { 17 | return new string[] { "value1", "value2" }; 18 | } 19 | 20 | /// 21 | /// 获取 22 | /// 23 | /// 24 | /// 25 | [HttpGet("{id}")] 26 | public ActionResult Get(int id) 27 | { 28 | return "value"; 29 | } 30 | 31 | // POST api/values 32 | [HttpPost] 33 | public void Post([FromBody] string value) 34 | { 35 | } 36 | 37 | // PUT api/values/5 38 | [HttpPut("{id}")] 39 | public void Put(int id, [FromBody] string value) 40 | { 41 | } 42 | 43 | // DELETE api/values/5 44 | [HttpDelete("{id}")] 45 | public void Delete(int id) 46 | { 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/ApiGroupTestHost/Controllers/App1Controller.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | 7 | namespace ApiGroupTestHost.Controllers 8 | { 9 | /// 10 | /// 测试 11 | /// 12 | [Route("api/app1/Values")] 13 | [ApiController] 14 | public class App1Controller : ControllerBase 15 | { 16 | /// 17 | /// 测试 18 | /// 19 | /// 20 | [HttpGet] 21 | public ActionResult> Get() 22 | { 23 | return new string[] { "value1", "value2" }; 24 | } 25 | 26 | // GET api/values/5 27 | [HttpGet("{id}")] 28 | public ActionResult Get(int id) 29 | { 30 | return "value"; 31 | } 32 | 33 | // POST api/values 34 | [HttpPost] 35 | public void Post([FromBody] string value) 36 | { 37 | } 38 | 39 | // PUT api/values/5 40 | [HttpPut("{id}")] 41 | public void Put(int id, [FromBody] string value) 42 | { 43 | } 44 | 45 | // DELETE api/values/5 46 | [HttpDelete("{id}")] 47 | public void Delete(int id) 48 | { 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/ApiGroupTestHost/Controllers/App2Controller.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | 7 | namespace ApiGroupTestHost.Controllers 8 | { 9 | /// 10 | /// 测试 11 | /// 12 | [Route("api/app2/Values")] 13 | [ApiController] 14 | public class App2Controller : ControllerBase 15 | { 16 | /// 17 | /// 测试 18 | /// 19 | /// 20 | [HttpGet] 21 | public ActionResult> Get() 22 | { 23 | return new string[] { "value1", "value2" }; 24 | } 25 | 26 | // GET api/values/5 27 | [HttpGet("{id}")] 28 | public ActionResult Get(int id) 29 | { 30 | return "value"; 31 | } 32 | 33 | // POST api/values 34 | [HttpPost] 35 | public void Post([FromBody] string value) 36 | { 37 | } 38 | 39 | // PUT api/values/5 40 | [HttpPut("{id}")] 41 | public void Put(int id, [FromBody] string value) 42 | { 43 | } 44 | 45 | // DELETE api/values/5 46 | [HttpDelete("{id}")] 47 | public void Delete(int id) 48 | { 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/TestHost3.1/Controllers/WeatherForecastController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | using Microsoft.Extensions.Logging; 7 | 8 | namespace TestHost3._1.Controllers 9 | { 10 | [ApiController] 11 | [Route("[controller]")] 12 | public class WeatherForecastController : ControllerBase 13 | { 14 | private static readonly string[] Summaries = new[] 15 | { 16 | "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" 17 | }; 18 | 19 | private readonly ILogger _logger; 20 | 21 | public WeatherForecastController(ILogger logger) 22 | { 23 | _logger = logger; 24 | } 25 | 26 | [HttpGet] 27 | public IEnumerable Get() 28 | { 29 | var rng = new Random(); 30 | return Enumerable.Range(1, 5).Select(index => new WeatherForecast 31 | { 32 | Date = DateTime.Now.AddDays(index), 33 | TemperatureC = rng.Next(-20, 55), 34 | Summary = Summaries[rng.Next(Summaries.Length)] 35 | }) 36 | .ToArray(); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Magicodes.SwaggerUI/SwaggerOperationFilter.cs: -------------------------------------------------------------------------------- 1 | #if NETCOREAPP3_1 2 | using Swashbuckle.AspNetCore.SwaggerGen; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using Microsoft.OpenApi.Models; 8 | 9 | namespace Magicodes.SwaggerUI 10 | { 11 | 12 | public class SwaggerOperationFilter : IOperationFilter 13 | { 14 | public void Apply(OpenApiOperation operation, OperationFilterContext context) 15 | { 16 | if (operation.Parameters == null) 17 | { 18 | return; 19 | } 20 | 21 | for (var i = 0; i < operation.Parameters.Count; ++i) 22 | { 23 | var parameter = operation.Parameters[i]; 24 | 25 | var enumType = context.ApiDescription.ParameterDescriptions[i].ParameterDescriptor.ParameterType; 26 | if (!enumType.IsEnum) 27 | { 28 | continue; 29 | } 30 | 31 | var schema = context.SchemaRepository.Schemas.GetOrAdd($"#/definitions/{enumType.Name}", () => 32 | context.SchemaGenerator.GenerateSchema(enumType, context.SchemaRepository) 33 | ); 34 | 35 | parameter.Schema = schema; 36 | } 37 | } 38 | } 39 | 40 | } 41 | #endif 42 | -------------------------------------------------------------------------------- /src/Magicodes.SwaggerUI/SwaggerEnumSchemaFilter.cs: -------------------------------------------------------------------------------- 1 | #if NETCOREAPP3_1 2 | using System; 3 | using System.Linq; 4 | using Microsoft.OpenApi.Any; 5 | using Microsoft.OpenApi.Models; 6 | using Swashbuckle.AspNetCore.Swagger; 7 | using Swashbuckle.AspNetCore.SwaggerGen; 8 | 9 | namespace Magicodes.SwaggerUI 10 | { 11 | 12 | public class SwaggerEnumSchemaFilter : ISchemaFilter 13 | { 14 | public void Apply(OpenApiSchema schema, SchemaFilterContext context) 15 | { 16 | if (context.Type == null) 17 | { 18 | return; 19 | } 20 | 21 | var type = Nullable.GetUnderlyingType(context.Type) ?? context.Type; 22 | if (!type.IsEnum || schema.Extensions.ContainsKey("x-enumNames")) 23 | { 24 | return; 25 | } 26 | 27 | var enumNames = new OpenApiArray(); 28 | enumNames.AddRange(Enum.GetNames(type).Select(_ => new OpenApiString(_))); 29 | schema.Extensions.Add("x-enumNames", enumNames); 30 | schema.Extensions.Add( 31 | "x-ms-enum", 32 | new OpenApiObject 33 | { 34 | ["name"] = new OpenApiString(type.Name), 35 | ["modelAsString"] = new OpenApiBoolean(true) 36 | } 37 | ); 38 | } 39 | } 40 | } 41 | #endif 42 | -------------------------------------------------------------------------------- /src/ApiGroupTestHost/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Warning" 5 | } 6 | }, 7 | "SwaggerDoc": { 8 | "IsEnabled": "true", 9 | //将枚举值以字符串显示 10 | "DescribeAllEnumsAsStrings": false, 11 | "SwaggerDocInfos": [ 12 | { 13 | "IsEnabled": "true", 14 | "Title": "APP1 API文档", 15 | "Version": "v1", 16 | "GroupName": "App1", 17 | "Description": "", 18 | "Contact": { 19 | "Name": "心莱科技Team1", 20 | "Email": "xinlai@xin-lai.com" 21 | }, 22 | "GroupUrlPrefix": "api/app1/" 23 | }, 24 | { 25 | "IsEnabled": "true", 26 | "Title": "APP2 API文档", 27 | "Version": "v2", 28 | "GroupName": "App2", 29 | "Description": "", 30 | "Contact": { 31 | "Name": "心莱科技Team2", 32 | "Email": "xinlai@xin-lai.com" 33 | }, 34 | "GroupUrlPrefix": "api/app2/", 35 | "HiddenApi": { 36 | "IsEnabled": "true", 37 | "Urls": [ 38 | { 39 | "Url": "app2/Values/{id}", 40 | "HttpMethod": "Delete" 41 | } 42 | ] 43 | } 44 | } 45 | ], 46 | "HiddenApi": { 47 | "IsEnabled": "true", 48 | "Urls": [ 49 | { "Url": "app1/Values/{id}" } 50 | ] 51 | }, 52 | "UseFullNameForSchemaId": "false" 53 | }, 54 | "AllowedHosts": "*" 55 | } 56 | -------------------------------------------------------------------------------- /src/Magicodes.SwaggerUI/Models/SwaggerConfigInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Magicodes.SwaggerUI.Models 6 | { 7 | /// 8 | /// Swagger配置信息 9 | /// 10 | public class SwaggerConfigInfo 11 | { 12 | /// 13 | /// 是否启用 14 | /// 15 | public bool IsEnabled { get; set; } 16 | 17 | 18 | /// 19 | /// 将枚举值以字符串显示 20 | /// 21 | public bool DescribeAllEnumsAsStrings { get; set; } 22 | 23 | /// 24 | /// Api文档列表 25 | /// 26 | public List SwaggerDocInfos { get; set; } 27 | 28 | /// 29 | /// 在界面上显示验证(Authorize)按钮,验证按钮处理逻辑基于 wwwroot/swagger/ui/index.html 30 | /// 31 | public bool Authorize { get; set; } 32 | 33 | /// 34 | /// 隐藏API配置 35 | /// 36 | public HiddenApiConfigInfo HiddenApi { get; set; } 37 | 38 | /// 39 | /// 是否启用API全名 40 | /// 41 | public bool UseFullNameForSchemaId { get; set; } 42 | 43 | /// 44 | /// 需要从嵌入资源中加载的程序集全称 45 | /// 46 | public string ManifestResourceAssembly { get; set; } 47 | 48 | /// 49 | /// 嵌入资源路径 50 | /// 51 | public string ManifestResourceUrl { get; set; } 52 | 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Magicodes.SwaggerUI/SwaggerOperationIdFilter.cs: -------------------------------------------------------------------------------- 1 | #if NETCOREAPP3_1 2 | using Microsoft.AspNetCore.Mvc.ApiExplorer; 3 | using Microsoft.OpenApi.Models; 4 | using Swashbuckle.AspNetCore.SwaggerGen; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Globalization; 8 | using System.Linq; 9 | using System.Text; 10 | 11 | namespace Magicodes.SwaggerUI 12 | { 13 | 14 | public class SwaggerOperationIdFilter : IOperationFilter 15 | { 16 | public void Apply(OpenApiOperation operation, OperationFilterContext context) 17 | { 18 | operation.OperationId = FriendlyId(context.ApiDescription); 19 | } 20 | 21 | private static string FriendlyId(ApiDescription apiDescription) 22 | { 23 | var parts = (RelativePathSansQueryString(apiDescription) + "/" + apiDescription.HttpMethod.ToLower()) 24 | .Split('/'); 25 | 26 | var builder = new StringBuilder(); 27 | foreach (var part in parts) 28 | { 29 | var trimmed = part.Trim('{', '}'); 30 | builder.AppendFormat("{0}{1}", 31 | (part.StartsWith("{") ? "By" : string.Empty), 32 | CultureInfo.InvariantCulture.TextInfo.ToTitleCase(trimmed) 33 | ); 34 | } 35 | 36 | return builder.ToString(); 37 | } 38 | 39 | private static string RelativePathSansQueryString(ApiDescription apiDescription) 40 | { 41 | return apiDescription.RelativePath.Split('?').First(); 42 | } 43 | } 44 | 45 | } 46 | #endif 47 | -------------------------------------------------------------------------------- /tools/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // 使用 IntelliSense 了解相关属性。 3 | // 悬停以查看现有属性的描述。 4 | // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "PowerShell", 9 | "request": "launch", 10 | "name": "PowerShell Launch Current File", 11 | "script": "${file}", 12 | "args": [], 13 | "cwd": "${file}" 14 | }, 15 | { 16 | "type": "PowerShell", 17 | "request": "launch", 18 | "name": "PowerShell Launch Current File in Temporary Console", 19 | "script": "${file}", 20 | "args": [], 21 | "cwd": "${file}", 22 | "createTemporaryIntegratedConsole": true 23 | }, 24 | { 25 | "type": "PowerShell", 26 | "request": "launch", 27 | "name": "PowerShell Launch Current File w/Args Prompt", 28 | "script": "${file}", 29 | "args": [ 30 | "${command:SpecifyScriptArgs}" 31 | ], 32 | "cwd": "${file}" 33 | }, 34 | { 35 | "type": "PowerShell", 36 | "request": "attach", 37 | "name": "PowerShell Attach to Host Process", 38 | "processId": "${command:PickPSHostProcess}", 39 | "runspaceId": 1 40 | }, 41 | { 42 | "type": "PowerShell", 43 | "request": "launch", 44 | "name": "PowerShell Interactive Session", 45 | "cwd": "${workspaceRoot}" 46 | } 47 | ] 48 | } -------------------------------------------------------------------------------- /src/Magicodes.SwaggerUI/Magicodes.SwaggerUI.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1;netcoreapp2.2;netstandard2.0 5 | SwaggerUI扩展 6 | 3.0.3 7 | True 8 | 湖南心莱信息科技有限公司 9 | http://www.cnblogs.com/codelove/ 10 | 雪雁 11 | 12 | Magicodes SwaggerUI扩展库。 13 | 官方网址:https://xin-lai.com 14 | 订阅号:麦扣聊技术 15 | 开源库地址:https://github.com/xin-lai 16 | 博客地址:http://www.cnblogs.com/codelove/ 17 | 交流QQ群:85318032 18 | 19 | https://github.com/xin-lai/Magicodes.SwaggerUI 20 | false 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/TestHost/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Magicodes.SwaggerUI; 6 | using Microsoft.AspNetCore.Builder; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.AspNetCore.Mvc; 9 | using Microsoft.Extensions.Configuration; 10 | using Microsoft.Extensions.DependencyInjection; 11 | using Microsoft.Extensions.Logging; 12 | using Microsoft.Extensions.Options; 13 | 14 | namespace TestHost 15 | { 16 | public class Startup 17 | { 18 | public Startup(IConfiguration configuration) 19 | { 20 | Configuration = configuration; 21 | } 22 | 23 | public IConfiguration Configuration { get; } 24 | 25 | // This method gets called by the runtime. Use this method to add services to the container. 26 | public void ConfigureServices(IServiceCollection services) 27 | { 28 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); 29 | //添加自定义API文档生成(支持文档配置) 30 | services.AddMagicodesSwaggerGen(Configuration); 31 | } 32 | 33 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 34 | public void Configure(IApplicationBuilder app, IHostingEnvironment env) 35 | { 36 | if (env.IsDevelopment()) 37 | { 38 | app.UseDeveloperExceptionPage(); 39 | } 40 | 41 | app.UseMvc(routes => routes.MapRoute( 42 | "default", 43 | "{controller=Home}/{action=Index}/{id?}")); 44 | 45 | //启用自定义API文档(支持文档配置) 46 | app.UseMagicodesSwaggerUI(Configuration); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/ApiGroupTestHost/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Magicodes.SwaggerUI; 6 | using Microsoft.AspNetCore.Builder; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.AspNetCore.Mvc; 9 | using Microsoft.Extensions.Configuration; 10 | using Microsoft.Extensions.DependencyInjection; 11 | using Microsoft.Extensions.Logging; 12 | using Microsoft.Extensions.Options; 13 | 14 | namespace ApiGroupTestHost 15 | { 16 | public class Startup 17 | { 18 | public Startup(IConfiguration configuration) 19 | { 20 | Configuration = configuration; 21 | } 22 | 23 | public IConfiguration Configuration { get; } 24 | 25 | // This method gets called by the runtime. Use this method to add services to the container. 26 | public void ConfigureServices(IServiceCollection services) 27 | { 28 | services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); 29 | 30 | //添加自定义API文档生成(支持文档配置) 31 | services.AddMagicodesSwaggerGen(Configuration); 32 | } 33 | 34 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 35 | public void Configure(IApplicationBuilder app, IHostingEnvironment env) 36 | { 37 | if (env.IsDevelopment()) 38 | { 39 | app.UseDeveloperExceptionPage(); 40 | } 41 | 42 | app.UseMvc(routes => routes.MapRoute( 43 | "default", 44 | "{controller=Home}/{action=Index}/{id?}")); 45 | 46 | //启用自定义API文档(支持文档配置) 47 | app.UseMagicodesSwaggerUI(Configuration); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Magicodes.SwaggerUI/Models/SwaggerDocInfo.cs: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // 3 | // Copyright (C) 2019-2030 湖南心莱信息科技有限公司 4 | // All rights reserved 5 | // 6 | // filename : SwaggerDocInfo.cs 7 | // description : 8 | // 9 | // created by 雪雁 at -- 10 | // 文档官网:https://docs.xin-lai.com 11 | // 公众号教程:麦扣聊技术 12 | // QQ群:85318032(编程交流) 13 | // Blog:http://www.cnblogs.com/codelove/ 14 | // 15 | // ====================================================================== 16 | 17 | namespace Magicodes.SwaggerUI.Models 18 | { 19 | /// 20 | /// API文档信息 21 | /// 22 | public class SwaggerDocInfo 23 | { 24 | /// 25 | /// 是否启用 26 | /// 27 | public bool IsEnabled { get; set; } 28 | 29 | /// 30 | /// 文档标题 31 | /// 32 | public string Title { get; set; } 33 | 34 | /// 35 | /// 分组名称 36 | /// 37 | public string GroupName { get; set; } = "v1"; 38 | 39 | /// 40 | /// 版本 41 | /// 42 | public string Version { get; set; } = "v1"; 43 | 44 | /// 45 | /// 描述 46 | /// 47 | public string Description { get; set; } 48 | 49 | /// 50 | /// 联系信息 51 | /// 52 | public ContactInfo Contact { get; set; } 53 | 54 | /// 55 | /// 分组Url前缀 56 | /// 57 | public string GroupUrlPrefix { get; set; } 58 | 59 | /// 60 | /// 隐藏API配置 61 | /// 62 | public HiddenApiConfigInfo HiddenApi { get; set; } 63 | } 64 | } -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /src/Magicodes.SwaggerUI/SwaggerEnumParameterFilter.cs: -------------------------------------------------------------------------------- 1 | #if NETCOREAPP3_1 2 | using Microsoft.OpenApi.Any; 3 | using Microsoft.OpenApi.Models; 4 | using Swashbuckle.AspNetCore.SwaggerGen; 5 | using System; 6 | using System.Collections; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Text; 10 | 11 | namespace Magicodes.SwaggerUI 12 | { 13 | public class SwaggerEnumParameterFilter : IParameterFilter 14 | { 15 | public void Apply(OpenApiParameter parameter, ParameterFilterContext context) 16 | { 17 | if (context.ApiParameterDescription.Type == null) 18 | { 19 | return; 20 | } 21 | 22 | var type = Nullable.GetUnderlyingType(context.ApiParameterDescription.Type) ?? context.ApiParameterDescription.Type; 23 | if (type.IsEnum) 24 | { 25 | AddEnumParamSpec(parameter, type, context); 26 | parameter.Required = type == context.ApiParameterDescription.Type; 27 | } 28 | else if (type.IsArray || (type.IsGenericType && type.GetInterfaces().Contains(typeof(IEnumerable)))) 29 | { 30 | var itemType = type.GetElementType() ?? type.GenericTypeArguments.First(); 31 | AddEnumSpec(parameter, itemType, context); 32 | } 33 | } 34 | 35 | private static void AddEnumSpec(OpenApiParameter parameter, Type type, ParameterFilterContext context) 36 | { 37 | var schema = context.SchemaRepository.Schemas.GetOrAdd($"#/definitions/{type.Name}", () => 38 | context.SchemaGenerator.GenerateSchema(type, context.SchemaRepository) 39 | ); 40 | 41 | if (schema.Reference == null || !type.IsEnum) 42 | { 43 | return; 44 | } 45 | 46 | parameter.Schema = schema; 47 | 48 | var enumNames = new OpenApiArray(); 49 | enumNames.AddRange(Enum.GetNames(type).Select(_ => new OpenApiString(_))); 50 | schema.Extensions.Add("x-enumNames", enumNames); 51 | } 52 | 53 | private static void AddEnumParamSpec(OpenApiParameter parameter, Type type, ParameterFilterContext context) 54 | { 55 | var schema = context.SchemaGenerator.GenerateSchema(type, context.SchemaRepository); 56 | if (schema.Reference == null) 57 | { 58 | return; 59 | } 60 | 61 | parameter.Schema = schema; 62 | 63 | var enumNames = new OpenApiArray(); 64 | enumNames.AddRange(Enum.GetNames(type).Select(_ => new OpenApiString(_))); 65 | schema.Extensions.Add("x-enumNames", enumNames); 66 | } 67 | 68 | 69 | } 70 | } 71 | #endif 72 | -------------------------------------------------------------------------------- /src/Magicodes.SwaggerUI.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29123.88 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Magicodes.SwaggerUI", "Magicodes.SwaggerUI\Magicodes.SwaggerUI.csproj", "{6DFD6EA6-C394-45F0-932C-3661BA144451}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{99C60890-9805-4D50-B661-3AEEA7784EC2}" 9 | ProjectSection(SolutionItems) = preProject 10 | ..\README.md = ..\README.md 11 | EndProjectSection 12 | EndProject 13 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApiGroupTestHost", "ApiGroupTestHost\ApiGroupTestHost.csproj", "{736CFBFB-0DE8-4238-B82F-766D7E46BE83}" 14 | EndProject 15 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestHost", "TestHost\TestHost.csproj", "{342ABF70-18A5-4CAB-B948-DCB647341BF7}" 16 | EndProject 17 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestHost3.1", "TestHost3.1\TestHost3.1.csproj", "{167AF511-4539-488C-9415-80FA2B3AE35F}" 18 | EndProject 19 | Global 20 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 21 | Debug|Any CPU = Debug|Any CPU 22 | Release|Any CPU = Release|Any CPU 23 | EndGlobalSection 24 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 25 | {6DFD6EA6-C394-45F0-932C-3661BA144451}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 26 | {6DFD6EA6-C394-45F0-932C-3661BA144451}.Debug|Any CPU.Build.0 = Debug|Any CPU 27 | {6DFD6EA6-C394-45F0-932C-3661BA144451}.Release|Any CPU.ActiveCfg = Release|Any CPU 28 | {6DFD6EA6-C394-45F0-932C-3661BA144451}.Release|Any CPU.Build.0 = Release|Any CPU 29 | {736CFBFB-0DE8-4238-B82F-766D7E46BE83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 30 | {736CFBFB-0DE8-4238-B82F-766D7E46BE83}.Debug|Any CPU.Build.0 = Debug|Any CPU 31 | {736CFBFB-0DE8-4238-B82F-766D7E46BE83}.Release|Any CPU.ActiveCfg = Release|Any CPU 32 | {736CFBFB-0DE8-4238-B82F-766D7E46BE83}.Release|Any CPU.Build.0 = Release|Any CPU 33 | {342ABF70-18A5-4CAB-B948-DCB647341BF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 34 | {342ABF70-18A5-4CAB-B948-DCB647341BF7}.Debug|Any CPU.Build.0 = Debug|Any CPU 35 | {342ABF70-18A5-4CAB-B948-DCB647341BF7}.Release|Any CPU.ActiveCfg = Release|Any CPU 36 | {342ABF70-18A5-4CAB-B948-DCB647341BF7}.Release|Any CPU.Build.0 = Release|Any CPU 37 | {167AF511-4539-488C-9415-80FA2B3AE35F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 38 | {167AF511-4539-488C-9415-80FA2B3AE35F}.Debug|Any CPU.Build.0 = Debug|Any CPU 39 | {167AF511-4539-488C-9415-80FA2B3AE35F}.Release|Any CPU.ActiveCfg = Release|Any CPU 40 | {167AF511-4539-488C-9415-80FA2B3AE35F}.Release|Any CPU.Build.0 = Release|Any CPU 41 | EndGlobalSection 42 | GlobalSection(SolutionProperties) = preSolution 43 | HideSolutionNode = FALSE 44 | EndGlobalSection 45 | GlobalSection(ExtensibilityGlobals) = postSolution 46 | SolutionGuid = {D15EDCA6-5121-4BD0-9C5F-62D46F58EF01} 47 | EndGlobalSection 48 | EndGlobal 49 | -------------------------------------------------------------------------------- /src/Magicodes.SwaggerUI/DictionaryExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Magicodes.SwaggerUI 6 | { 7 | /// 8 | /// Extension methods for Dictionary. 9 | /// 10 | public static class DictionaryExtensions 11 | { 12 | /// 13 | /// This method is used to try to get a value in a dictionary if it does exists. 14 | /// 15 | /// Type of the value 16 | /// The collection object 17 | /// Key 18 | /// Value of the key (or default value if key not exists) 19 | /// True if key does exists in the dictionary 20 | internal static bool TryGetValue(this IDictionary dictionary, string key, out T value) 21 | { 22 | object valueObj; 23 | if (dictionary.TryGetValue(key, out valueObj) && valueObj is T) 24 | { 25 | value = (T)valueObj; 26 | return true; 27 | } 28 | 29 | value = default(T); 30 | return false; 31 | } 32 | 33 | /// 34 | /// Gets a value from the dictionary with given key. Returns default value if can not find. 35 | /// 36 | /// Dictionary to check and get 37 | /// Key to find the value 38 | /// Type of the key 39 | /// Type of the value 40 | /// Value if found, default if can not found. 41 | public static TValue GetOrDefault(this IDictionary dictionary, TKey key) 42 | { 43 | TValue obj; 44 | return dictionary.TryGetValue(key, out obj) ? obj : default(TValue); 45 | } 46 | 47 | /// 48 | /// Gets a value from the dictionary with given key. Returns default value if can not find. 49 | /// 50 | /// Dictionary to check and get 51 | /// Key to find the value 52 | /// A factory method used to create the value if not found in the dictionary 53 | /// Type of the key 54 | /// Type of the value 55 | /// Value if found, default if can not found. 56 | public static TValue GetOrAdd(this IDictionary dictionary, TKey key, Func factory) 57 | { 58 | TValue obj; 59 | if (dictionary.TryGetValue(key, out obj)) 60 | { 61 | return obj; 62 | } 63 | 64 | return dictionary[key] = factory(key); 65 | } 66 | 67 | /// 68 | /// Gets a value from the dictionary with given key. Returns default value if can not find. 69 | /// 70 | /// Dictionary to check and get 71 | /// Key to find the value 72 | /// A factory method used to create the value if not found in the dictionary 73 | /// Type of the key 74 | /// Type of the value 75 | /// Value if found, default if can not found. 76 | public static TValue GetOrAdd(this IDictionary dictionary, TKey key, Func factory) 77 | { 78 | return dictionary.GetOrAdd(key, k => factory()); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Magicodes.SwaggerUI 2 | 通过配置文件简单配置即可快速完成SwaggerUI的配置,包括: 3 | - SwaggerUI的文档信息 4 | - API分组 5 | - API隐藏 6 | - API JSON生成(枚举、API架构Id) 7 | - 验证 8 | - 自定义页面 9 | 10 | 支持.NET Core 2.2和3.1。版本日志和使用教程见下文。 11 | 12 | 注意:AddCustomSwaggerGen和UseCustomSwaggerUI已分别替换为“AddMagicodesSwaggerGen”、“UseMagicodesSwaggerUI”。 13 | 14 | ## 特点 15 | - 通过配置文件简单配置即可完成SwaggerUI的API格式JSON生成和集成 16 | ![](./res/3.png "图3") 17 | - 支持API分组和隐藏 18 | ![](./res/1.png "图1") 19 | ![](./res/2.png "图1") 20 | - 支持自定义页面和验证 21 | 22 | ## Nuget包 23 | 24 | | 名称 | Nuget | 25 | |----------|:-------------:| 26 | | Magicodes.SwaggerUI | [![NuGet](https://buildstats.info/nuget/Magicodes.SwaggerUI)](https://www.nuget.org/packages/Magicodes.SwaggerUI) | 27 | 28 | ### Magicodes Nuget包推荐 29 | 30 | ## 相关Nuget包 31 | 32 | | 名称 | 说明 | Nuget | GitHUb | 33 | |----------|:-------------:|:-------------:|:-------------:| 34 | | Magicodes.IE.Excel |Excel导入导出| [![NuGet](https://buildstats.info/nuget/Magicodes.IE.Excel)](https://www.nuget.org/packages/Magicodes.IE.Excel) |[dotnetcore](https://github.com/dotnetcore)/**[Magicodes.IE](https://github.com/dotnetcore/Magicodes.IE)**| 35 | | Magicodes.IE.Core |导入导出核心库| [![NuGet](https://buildstats.info/nuget/Magicodes.IE.Core)](https://www.nuget.org/packages/Magicodes.IE.Core) |[dotnetcore](https://github.com/dotnetcore)/**[Magicodes.IE](https://github.com/dotnetcore/Magicodes.IE)**| 36 | | Magicodes.IE.HTML | HTML导入导出|[![NuGet](https://buildstats.info/nuget/Magicodes.IE.HTML)](https://www.nuget.org/packages/Magicodes.IE.HTML) |[dotnetcore](https://github.com/dotnetcore)/**[Magicodes.IE](https://github.com/dotnetcore/Magicodes.IE)**| 37 | | Magicodes.IE.Pdf |Pdf导出| [![NuGet](https://buildstats.info/nuget/Magicodes.IE.Pdf)](https://www.nuget.org/packages/Magicodes.IE.Pdf) |[dotnetcore](https://github.com/dotnetcore)/**[Magicodes.IE](https://github.com/dotnetcore/Magicodes.IE)**| 38 | | Magicodes.IE.Word |Word导出| [![NuGet](https://buildstats.info/nuget/Magicodes.IE.Word)](https://www.nuget.org/packages/Magicodes.IE.Word) |[dotnetcore](https://github.com/dotnetcore)/**[Magicodes.IE](https://github.com/dotnetcore/Magicodes.IE)**| 39 | | Magicodes.IE.Csv |Csv导入导出| [![NuGet](https://buildstats.info/nuget/Magicodes.IE.Csv)](https://www.nuget.org/packages/Magicodes.IE.Csv) |[dotnetcore](https://github.com/dotnetcore)/**[Magicodes.IE](https://github.com/dotnetcore/Magicodes.IE)**| 40 | | Magicodes.WeChat.MiniProgram |小程序SDK |[![NuGet](https://buildstats.info/nuget/Magicodes.WeChat.MiniProgram)](https://www.nuget.org/packages/Magicodes.WeChat.MiniProgram) |**[Magicodes.WxMiniProgram.Sdk](https://github.com/xin-lai/Magicodes.WxMiniProgram.Sdk)**| 41 | | Magicodes.Sms.Aliyun |阿里云短信 | [![NuGet](https://buildstats.info/nuget/Magicodes.Sms.Aliyun)](https://www.nuget.org/packages/Magicodes.Sms.Aliyun) |[xin-lai](https://github.com/xin-lai)/**[Magicodes.Sms](https://github.com/xin-lai/Magicodes.Sms)**| 42 | | Magicodes.Sms.Core | 短信核心库 | [![NuGet](https://buildstats.info/nuget/Magicodes.Sms.Core)](https://www.nuget.org/packages/Magicodes.Sms.Core) |[xin-lai](https://github.com/xin-lai)/**[Magicodes.Sms](https://github.com/xin-lai/Magicodes.Sms)**| 43 | | Magicodes.Sms.Aliyun.Abp | 阿里云短信Abp模块 | [![NuGet](https://buildstats.info/nuget/Magicodes.Sms.Aliyun.Abp)](https://www.nuget.org/packages/Magicodes.Sms.Aliyun.Abp) |[xin-lai](https://github.com/xin-lai)/**[Magicodes.Sms](https://github.com/xin-lai/Magicodes.Sms)**| 44 | | Magicodes.Storage.Core |通用存储核心库| [![NuGet](https://buildstats.info/nuget/Magicodes.Storage.Core)](https://www.nuget.org/packages/Magicodes.Storage.Core) |[xin-lai](https://github.com/xin-lai)/**[Magicodes.Storage](https://github.com/xin-lai/Magicodes.Storage)**| 45 | | Magicodes.Storage.AliyunOss.Core |阿里云OSS存储| [![NuGet](https://buildstats.info/nuget/Magicodes.Storage.AliyunOss.Core)](https://www.nuget.org/packages/Magicodes.Storage.AliyunOss.Core) |[xin-lai](https://github.com/xin-lai)/**[Magicodes.Storage](https://github.com/xin-lai/Magicodes.Storage)**| 46 | | Magicodes.Storage.Local.Core |本地存储| [![NuGet](https://buildstats.info/nuget/Magicodes.Storage.Local.Core)](https://www.nuget.org/packages/Magicodes.Storage.Local.Core) |[xin-lai](https://github.com/xin-lai)/**[Magicodes.Storage](https://github.com/xin-lai/Magicodes.Storage)**| 47 | | Magicodes.Storage.Tencent.Core |腾讯云存储| [![NuGet](https://buildstats.info/nuget/Magicodes.Storage.Tencent.Core)](https://www.nuget.org/packages/Magicodes.Storage.Tencent.Core) |[xin-lai](https://github.com/xin-lai)/**[Magicodes.Storage](https://github.com/xin-lai/Magicodes.Storage)**| 48 | | Magicodes.Storage.Abp.Core | 通用存储ABP模块集成| [![NuGet](https://buildstats.info/nuget/Magicodes.Storage.Abp.Core)](https://www.nuget.org/packages/Magicodes.Storage.Abp.Core) |[xin-lai](https://github.com/xin-lai)/**[Magicodes.Storage](https://github.com/xin-lai/Magicodes.Storage)**| 49 | | Magicodes.WeChat.SDK.Core |微信SDK | [![NuGet](https://buildstats.info/nuget/Magicodes.WeChat.SDK.Core)](https://www.nuget.org/packages/Magicodes.WeChat.SDK.Core) |[xin-lai](https://github.com/xin-lai)/**[Magicodes.WeChat.SDK](https://github.com/xin-lai/Magicodes.WeChat.SDK)**| 50 | | Magicodes.SwaggerUI |SwaggerUI API快速配置和分组| [![NuGet](https://buildstats.info/nuget/Magicodes.SwaggerUI)](https://www.nuget.org/packages/Magicodes.SwaggerUI) |[xin-lai](https://github.com/xin-lai)/**[Magicodes.SwaggerUI](https://github.com/xin-lai/Magicodes.SwaggerUI)**| 51 | | Magicodes.Pay.Alipay |支付宝支付库| [![NuGet](https://buildstats.info/nuget/Magicodes.Pay.Alipay)](https://www.nuget.org/packages/Magicodes.Pay.Alipay) |[xin-lai](https://github.com/xin-lai)/**[Magicodes.Pay](https://github.com/xin-lai/Magicodes.Pay)**| 52 | | Magicodes.Pay.Notify |支付通用回调库| [![NuGet](https://buildstats.info/nuget/Magicodes.Pay.Notify)](https://www.nuget.org/packages/Magicodes.Pay.Notify) |[xin-lai](https://github.com/xin-lai)/**[Magicodes.Pay](https://github.com/xin-lai/Magicodes.Pay)**| 53 | | Magicodes.Pay.Wxpay |微信支付库| [![NuGet](https://buildstats.info/nuget/Magicodes.Pay.Wxpay)](https://www.nuget.org/packages/Magicodes.Pay.Wxpay) |[xin-lai](https://github.com/xin-lai)/**[Magicodes.Pay](https://github.com/xin-lai/Magicodes.Pay)**| 54 | | Magicodes.Pay.Alipay.Global |国际支付宝支付库 | [![NuGet](https://buildstats.info/nuget/Magicodes.Pay.Alipay.Global)](https://www.nuget.org/packages/Magicodes.Pay.Alipay.Global) |[xin-lai](https://github.com/xin-lai)/**[Magicodes.Pay](https://github.com/xin-lai/Magicodes.Pay)**| 55 | | Magicodes.Pay.Allinpay | 通联支付库 | [![NuGet](https://buildstats.info/nuget/Magicodes.Pay.Allinpay)](https://www.nuget.org/packages/Magicodes.Pay.Allinpay) |[xin-lai](https://github.com/xin-lai)/**[Magicodes.Pay](https://github.com/xin-lai/Magicodes.Pay)**| 56 | | Magicodes.Pay.Abp | ABP 支付通用封装库| [![NuGet](https://buildstats.info/nuget/Magicodes.Pay.Abp)](https://www.nuget.org/packages/Magicodes.Pay.Abp) |[xin-lai](https://github.com/xin-lai)/**[Magicodes.Pay](https://github.com/xin-lai/Magicodes.Pay)**| 57 | | Magicodes.Pay.Abp.Allinpay |ABP 通联支付模块| [![NuGet](https://buildstats.info/nuget/Magicodes.Pay.Abp.Allinpay)](https://www.nuget.org/packages/Magicodes.Pay.Abp.Allinpay) |[xin-lai](https://github.com/xin-lai)/**[Magicodes.Pay](https://github.com/xin-lai/Magicodes.Pay)**| 58 | | Magicodes.Pay.Abp.Wxpay | ABP 微信支付模块| [![NuGet](https://buildstats.info/nuget/Magicodes.Pay.Abp.Wxpay)](https://www.nuget.org/packages/Magicodes.Pay.Abp.Wxpay) |[xin-lai](https://github.com/xin-lai)/**[Magicodes.Pay](https://github.com/xin-lai/Magicodes.Pay)**| 59 | | Magicodes.Pay.Alipay.Global | ABP 国际支付宝模块 | [![NuGet](https://buildstats.info/nuget/Magicodes.Pay.Alipay.Global)](https://www.nuget.org/packages/Magicodes.Pay.Alipay.Global) |[xin-lai](https://github.com/xin-lai)/**[Magicodes.Pay](https://github.com/xin-lai/Magicodes.Pay)**| 60 | | Magicodes.Pay.Alipay | ABP 支付宝模块 | [![NuGet](https://buildstats.info/nuget/Magicodes.Pay.Alipay)](https://www.nuget.org/packages/Magicodes.Pay.Alipay) |[xin-lai](https://github.com/xin-lai)/**[Magicodes.Pay](https://github.com/xin-lai/Magicodes.Pay)**| 61 | | Magicodes.Abp.Castle.NLog | ABP Nlog支持模块 | [![NuGet](https://buildstats.info/nuget/Magicodes.Abp.Castle.NLog)](https://www.nuget.org/packages/Magicodes.Abp.Castle.NLog) |[xin-lai](https://github.com/xin-lai)/**[Abp.Castle.NLog](https://github.com/xin-lai/Abp.Castle.NLog)**| 62 | | Magicodes.WxMiniProgram.Sdk |微信小程序SDK| [![NuGet](https://buildstats.info/nuget/Magicodes.WxMiniProgram.Sdk)](https://www.nuget.org/packages/Magicodes.WxMiniProgram.Sdk) |[xin-lai](https://github.com/xin-lai)/**[Magicodes.WxMiniProgram.Sdk](https://github.com/xin-lai/Magicodes.WxMiniProgram.Sdk)**| 63 | | Magicodes.WxMiniProgram.Sdk.Abp |微信小程序SDK Abp模块| [![NuGet](https://buildstats.info/nuget/Magicodes.WxMiniProgram.Sdk.Abp)](https://www.nuget.org/packages/Magicodes.WxMiniProgram.Sdk.Abp) |[xin-lai](https://github.com/xin-lai)/**[Magicodes.WxMiniProgram.Sdk](https://github.com/xin-lai/Magicodes.WxMiniProgram.Sdk)**| 64 | | Magicodes.Dingtalk.SDK |钉钉SDK| [![NuGet](https://buildstats.info/nuget/Magicodes.Dingtalk.SDK)](https://www.nuget.org/packages/Magicodes.Dingtalk.SDK) | [xin-lai](https://github.com/xin-lai)/**[Magicodes.Dingtalk.SDK](https://github.com/xin-lai/Magicodes.Dingtalk.SDK)**| 65 | | Magicodes.DynamicSqlApi.Core | 根据SQL自动解析生成动态API | [![NuGet](https://buildstats.info/nuget/Magicodes.DynamicSqlApi.Core)](https://www.nuget.org/packages/Magicodes.DynamicSqlApi.Core) | **[Magicodes.DynamicSqlApi](https://github.com/xin-lai/Magicodes.DynamicSqlApi)** | 66 | | Magicodes.DynamicSqlApi.All | 根据SQL自动解析生成动态API | [![NuGet](https://buildstats.info/nuget/Magicodes.DynamicSqlApi.All)](https://www.nuget.org/packages/Magicodes.DynamicSqlApi.All) | **[Magicodes.DynamicSqlApi](https://github.com/xin-lai/Magicodes.DynamicSqlApi)** | 67 | | Magicodes.DynamicSqlApi.CsScript |根据SQL自动解析生成动态API | [![NuGet](https://buildstats.info/nuget/Magicodes.DynamicSqlApi.CsScript)](https://www.nuget.org/packages/Magicodes.DynamicSqlApi.CsScript) | **[Magicodes.DynamicSqlApi](https://github.com/xin-lai/Magicodes.DynamicSqlApi)** | 68 | | Magicodes.DynamicSqlApi.Dapper | 根据SQL自动解析生成动态API | [![NuGet](https://buildstats.info/nuget/Magicodes.DynamicSqlApi.Dapper)](https://www.nuget.org/packages/Magicodes.DynamicSqlApi.Dapper) | **[Magicodes.DynamicSqlApi](https://github.com/xin-lai/Magicodes.DynamicSqlApi)** | 69 | | Magicodes.DynamicSqlApi.SqlServer | 根据SQL自动解析生成动态API | [![NuGet](https://buildstats.info/nuget/Magicodes.DynamicSqlApi.SqlServer)](https://www.nuget.org/packages/Magicodes.DynamicSqlApi.SqlServer) | **[Magicodes.DynamicSqlApi](https://github.com/xin-lai/Magicodes.DynamicSqlApi)** | 70 | 71 | ## 联系我们 72 | 73 | > #### 订阅号 74 | 75 | 关注“麦扣聊技术”微信订阅号可以获得最新文章、教程、文档。 76 | 77 | ![](./res/wechat.jpg "麦扣聊技术") 78 | 79 | 80 | > #### QQ群 81 | 82 | - 编程交流群<85318032> 83 | 84 | - 产品交流群<897857351> 85 | 86 | > #### 文档官网&官方博客 87 | 88 | - 文档官网: 89 | - 博客: 90 | 91 | 92 | > #### 其他开源库 93 | 94 | - 95 | - 96 | 97 | ## 更新日志 98 | 99 | ### 2019.03.07 100 | 101 | - 【Nuget】Magicodes.SwaggerUI 3.0.2 102 | - 【升级】支持.NET Core 3.1 103 | - 【重构】支持自定义逻辑编写: 104 | - AddMagicodesSwaggerGen添加Action参数,可以实现自定义逻辑 105 | - UseMagicodesSwaggerUI添加Action参数,可以实现自定义逻辑 106 | 107 | ### 2019.10.21 108 | 109 | - 【Nuget】Magicodes.SwaggerUI 2.0.4 110 | - 【升级】单个文档不分组,显示所有API 111 | - 【梳理】梳理目录结构 112 | - 【修复】修复本地开发环境运行时不加载文档注释的问题 113 | - 【修改】自动移除GroupUrlPrefix的前后空格以及“/”前缀 114 | - 【升级】在全局隐藏API的基础上,支持分组API隐藏 115 | - 【升级】API隐藏支持HTTP方法配置,默认“*” 116 | 117 | ### 2019.10.19 118 | - 【升级】支持API分组,支持非侵入式配置,无需修改代码,仅通过配置即可完成API分组(见下面示例) 119 | - 【重构】重构整体逻辑 120 | 121 | ## Demo 122 | ### 配置Demo 123 | ``` 124 | "SwaggerDoc": { 125 | "IsEnabled": "true", 126 | //将枚举值以字符串显示 127 | "DescribeAllEnumsAsStrings": false, 128 | "SwaggerDocInfos": [ 129 | { 130 | "IsEnabled": "true", 131 | "Title": "APP1 API文档", 132 | "Version": "v1", 133 | "GroupName": "App1", 134 | "Description": "", 135 | "Contact": { 136 | "Name": "心莱科技Team1", 137 | "Email": "xinlai@xin-lai.com" 138 | }, 139 | "GroupUrlPrefix": "api/app1/" 140 | }, 141 | { 142 | "IsEnabled": "true", 143 | "Title": "APP2 API文档", 144 | "Version": "v2", 145 | "GroupName": "App2", 146 | "Description": "", 147 | "Contact": { 148 | "Name": "心莱科技Team2", 149 | "Email": "xinlai@xin-lai.com" 150 | }, 151 | "GroupUrlPrefix": "api/app2/", 152 | "HiddenApi": { 153 | "IsEnabled": "true", 154 | "Urls": [ 155 | { 156 | "Url": "app2/Values/{id}", 157 | "HttpMethod": "Delete" 158 | } 159 | ] 160 | } 161 | } 162 | ], 163 | "HiddenApi": { 164 | "IsEnabled": "true", 165 | "Urls": [ 166 | { "Url": "app1/Values/{id}" } 167 | ] 168 | }, 169 | "UseFullNameForSchemaId": "false" 170 | } 171 | ``` 172 | 173 | ### 注入代码: 174 | 175 | ``` 176 | //添加自定义API文档生成(支持文档配置) 177 | public IServiceProvider ConfigureServices(IServiceCollection services) 178 | { 179 | services.AddMagicodesSwaggerGen(_appConfiguration); 180 | } 181 | 182 | public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) 183 | { 184 | //启用自定义API文档(支持文档配置) 185 | app.UseMagicodesSwaggerUI(_appConfiguration); 186 | } 187 | ``` -------------------------------------------------------------------------------- /src/Magicodes.SwaggerUI/Extentions.cs: -------------------------------------------------------------------------------- 1 | using Magicodes.SwaggerUI.Models; 2 | using Microsoft.AspNetCore.Builder; 3 | using Microsoft.AspNetCore.Mvc.ApiExplorer; 4 | using Microsoft.Extensions.Configuration; 5 | using Microsoft.Extensions.DependencyInjection; 6 | #if NETCOREAPP3_1 7 | using Microsoft.OpenApi.Models; 8 | #endif 9 | using Swashbuckle.AspNetCore.Swagger; 10 | using Swashbuckle.AspNetCore.SwaggerGen; 11 | using Swashbuckle.AspNetCore.SwaggerUI; 12 | using System; 13 | using System.Collections.Generic; 14 | using System.IO; 15 | using System.Linq; 16 | using System.Reflection; 17 | 18 | namespace Magicodes.SwaggerUI 19 | { 20 | /// 21 | /// 22 | /// 23 | public static class Extentions 24 | { 25 | #if NETCOREAPP3_1 26 | /// 27 | /// 添加自定义API文档生成(支持文档配置) 28 | /// 29 | /// 30 | /// 31 | public static void AddMagicodesSwaggerGen(this IServiceCollection services, IConfiguration configuration, Action setupAction = null) 32 | { 33 | var docConfigInfo = GetApiDocsConfigInfo(configuration); 34 | if (docConfigInfo == null) 35 | { 36 | return; 37 | } 38 | var webRootDirectory = GetRootPath(); 39 | //设置API文档生成 40 | services.AddSwaggerGen(options => 41 | { 42 | options.OperationFilter(); 43 | options.OperationFilter(); 44 | options.ParameterFilter(); 45 | options.CustomDefaultSchemaIdSelector(); 46 | //将所有枚举显示为字符串 47 | if (docConfigInfo.DescribeAllEnumsAsStrings) 48 | { 49 | options.SchemaFilter(); 50 | } 51 | 52 | if (docConfigInfo.Authorize) 53 | { 54 | //以便于在界面上显示验证(Authorize)按钮,验证按钮处理逻辑基于 wwwroot/swagger/ui/index.html 55 | options.AddSecurityDefinition("Bearer", 56 | new Microsoft.OpenApi.Models.OpenApiSecurityScheme 57 | { 58 | In = Microsoft.OpenApi.Models.ParameterLocation.Header, 59 | Description = "Please enter into field the word 'Bearer' following by space and JWT", 60 | Name = "Authorization", 61 | Type = Microsoft.OpenApi.Models.SecuritySchemeType.ApiKey 62 | }); 63 | options.AddSecurityRequirement(new OpenApiSecurityRequirement() 64 | { 65 | { 66 | new OpenApiSecurityScheme 67 | { 68 | Reference = new OpenApiReference 69 | { 70 | Type = ReferenceType.SecurityScheme, 71 | Id = "Bearer" 72 | }, 73 | Scheme = "oauth2", 74 | Name = "Bearer", 75 | In = ParameterLocation.Header, 76 | 77 | }, 78 | new List() 79 | } 80 | }); 81 | } 82 | 83 | if (docConfigInfo.UseFullNameForSchemaId) 84 | { 85 | //使用全名作为架构id 86 | options.CustomSchemaIds(p => p.FullName); 87 | } 88 | 89 | foreach (var doc in docConfigInfo.SwaggerDocInfos) 90 | { 91 | options.SwaggerDoc(doc.GroupName ?? doc.Version, new Microsoft.OpenApi.Models.OpenApiInfo 92 | { 93 | Title = doc.Title, 94 | Version = doc.Version, 95 | Description = doc.Description, 96 | Contact = new Microsoft.OpenApi.Models.OpenApiContact 97 | { 98 | Name = doc.Contact?.Name, 99 | Email = doc.Contact?.Email 100 | } 101 | }); 102 | } 103 | 104 | //遍历所有xml并加载 105 | var paths = new List(); 106 | var plusPath = Path.Combine(webRootDirectory ?? throw new InvalidOperationException(), "PlugIns"); 107 | if (Directory.Exists(plusPath)) 108 | { 109 | var xmlFiles = new DirectoryInfo(plusPath).GetFiles("*.xml"); 110 | paths.AddRange(xmlFiles.Select(item => item.FullName)); 111 | } 112 | var binXmlFiles = new DirectoryInfo(webRootDirectory).GetFiles("*.xml", SearchOption.TopDirectoryOnly); 113 | paths.AddRange(binXmlFiles.Select(item => item.FullName)); 114 | 115 | foreach (var filePath in paths) 116 | { 117 | options.IncludeXmlComments(filePath); 118 | } 119 | 120 | //接口分组和隐藏处理 121 | options.DocInclusionPredicate((docName, apiDescription) => 122 | { 123 | //全局API隐藏逻辑处理 124 | if (IsHiddenApi(docConfigInfo.HiddenApi, apiDescription)) return false; 125 | 126 | //只有一个配置则不分组 127 | if (docConfigInfo.SwaggerDocInfos.Count <= 1) 128 | { 129 | return true; 130 | } 131 | 132 | var doc = docConfigInfo.SwaggerDocInfos.FirstOrDefault(p => 133 | p.GroupName == docName); 134 | if (doc == null) 135 | { 136 | return false; 137 | } 138 | 139 | //分组API隐藏逻辑处理 140 | if (IsHiddenApi(doc.HiddenApi, apiDescription)) return false; 141 | 142 | //API分组处理 143 | if (!string.IsNullOrEmpty(doc.GroupUrlPrefix)) 144 | { 145 | //分组处理:隐藏组Url不一致的接口 146 | return apiDescription.RelativePath.StartsWith(doc.GroupUrlPrefix, 147 | StringComparison.OrdinalIgnoreCase); 148 | } 149 | return false; 150 | 151 | }); 152 | 153 | setupAction?.Invoke(options, docConfigInfo); 154 | }); 155 | } 156 | #else 157 | /// 158 | /// 添加自定义API文档生成(支持文档配置) 159 | /// 160 | /// 161 | /// 162 | public static void AddMagicodesSwaggerGen(this IServiceCollection services, IConfiguration configuration,Action setupAction = null) 163 | { 164 | var docConfigInfo = GetApiDocsConfigInfo(configuration); 165 | if (docConfigInfo == null) 166 | { 167 | return; 168 | } 169 | var webRootDirectory = GetRootPath(); 170 | //设置API文档生成 171 | services.AddSwaggerGen(options => 172 | { 173 | //将所有枚举显示为字符串 174 | if (docConfigInfo.DescribeAllEnumsAsStrings) 175 | { 176 | options.DescribeAllEnumsAsStrings(); 177 | } 178 | 179 | if (docConfigInfo.Authorize) 180 | { 181 | //以便于在界面上显示验证(Authorize)按钮,验证按钮处理逻辑基于 wwwroot/swagger/ui/index.html 182 | options.AddSecurityDefinition("Bearer", new BasicAuthScheme()); 183 | } 184 | 185 | if (docConfigInfo.UseFullNameForSchemaId) 186 | { 187 | //使用全名作为架构id 188 | options.CustomSchemaIds(p => p.FullName); 189 | } 190 | 191 | foreach (var doc in docConfigInfo.SwaggerDocInfos) 192 | { 193 | options.SwaggerDoc(doc.GroupName ?? doc.Version, new Info 194 | { 195 | Title = doc.Title, 196 | Version = doc.Version, 197 | Description = doc.Description, 198 | Contact = new Contact 199 | { 200 | Name = doc.Contact?.Name, 201 | Email = doc.Contact?.Email 202 | } 203 | }); 204 | } 205 | 206 | //遍历所有xml并加载 207 | var paths = new List(); 208 | var plusPath = Path.Combine(webRootDirectory ?? throw new InvalidOperationException(), "PlugIns"); 209 | if (Directory.Exists(plusPath)) 210 | { 211 | var xmlFiles = new DirectoryInfo(plusPath).GetFiles("*.xml"); 212 | paths.AddRange(xmlFiles.Select(item => item.FullName)); 213 | } 214 | var binXmlFiles = new DirectoryInfo(webRootDirectory).GetFiles("*.xml", SearchOption.TopDirectoryOnly); 215 | paths.AddRange(binXmlFiles.Select(item => item.FullName)); 216 | 217 | foreach (var filePath in paths) 218 | { 219 | options.IncludeXmlComments(filePath); 220 | } 221 | 222 | //接口分组和隐藏处理 223 | options.DocInclusionPredicate((docName, apiDescription) => 224 | { 225 | //全局API隐藏逻辑处理 226 | if (IsHiddenApi(docConfigInfo.HiddenApi, apiDescription)) return false; 227 | 228 | //只有一个配置则不分组 229 | if (docConfigInfo.SwaggerDocInfos.Count <= 1) 230 | { 231 | return true; 232 | } 233 | 234 | var doc = docConfigInfo.SwaggerDocInfos.FirstOrDefault(p => 235 | p.GroupName == docName); 236 | if (doc == null) 237 | { 238 | return false; 239 | } 240 | 241 | //分组API隐藏逻辑处理 242 | if (IsHiddenApi(doc.HiddenApi, apiDescription)) return false; 243 | 244 | //API分组处理 245 | if (!string.IsNullOrEmpty(doc.GroupUrlPrefix)) 246 | { 247 | //分组处理:隐藏组Url不一致的接口 248 | return apiDescription.RelativePath.StartsWith(doc.GroupUrlPrefix, 249 | StringComparison.OrdinalIgnoreCase); 250 | } 251 | return false; 252 | 253 | }); 254 | 255 | setupAction?.Invoke(options, docConfigInfo); 256 | }); 257 | } 258 | 259 | 260 | #endif 261 | 262 | 263 | /// 264 | /// 是否隐藏此API 265 | /// 266 | /// 267 | /// 268 | /// 269 | private static bool IsHiddenApi(HiddenApiConfigInfo hiddenApiConfigInfo, ApiDescription apiDescription) 270 | { 271 | if (hiddenApiConfigInfo != null && hiddenApiConfigInfo.IsEnabled && hiddenApiConfigInfo.Urls != null && hiddenApiConfigInfo.Urls.Any()) 272 | { 273 | foreach (var item in hiddenApiConfigInfo.Urls) 274 | { 275 | if (apiDescription.RelativePath.IndexOf(item.Url?.Trim(), StringComparison.OrdinalIgnoreCase) != -1 && (item.HttpMethod == "*" || apiDescription.HttpMethod.Equals(item.HttpMethod, StringComparison.OrdinalIgnoreCase))) 276 | { 277 | return true; 278 | } 279 | } 280 | } 281 | return false; 282 | } 283 | 284 | /// 285 | /// 获取文件根路径 286 | /// 287 | /// 288 | private static string GetRootPath() 289 | { 290 | var path = AppDomain.CurrentDomain.BaseDirectory; 291 | if (string.IsNullOrWhiteSpace(path)) 292 | { 293 | path = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); 294 | } 295 | return path; 296 | } 297 | 298 | /// 299 | /// 获取配置信息 300 | /// 301 | /// 302 | /// 303 | private static SwaggerConfigInfo GetApiDocsConfigInfo(IConfiguration configuration) 304 | { 305 | var configs = configuration?["SwaggerDoc:IsEnabled"] != null 306 | ? configuration.GetSection("SwaggerDoc").Get() 307 | : null; 308 | if (configs.SwaggerDocInfos != null) 309 | { 310 | foreach (var item in configs.SwaggerDocInfos) 311 | { 312 | if (!string.IsNullOrWhiteSpace(item.GroupUrlPrefix)) 313 | { 314 | item.GroupUrlPrefix = item.GroupUrlPrefix.Trim().TrimStart('/'); 315 | } 316 | } 317 | } 318 | return configs; 319 | } 320 | 321 | /// 322 | /// 启用自定义API文档(支持文档配置) 323 | /// 324 | /// 325 | /// 326 | public static void UseMagicodesSwaggerUI(this IApplicationBuilder app, IConfiguration configuration, Action setupAction = null) 327 | { 328 | var docConfigInfo = GetApiDocsConfigInfo(configuration); 329 | if (docConfigInfo == null) 330 | { 331 | return; 332 | } 333 | 334 | app.UseSwagger(c => 335 | { 336 | if (docConfigInfo.SwaggerDocInfos.Count > 1) 337 | { 338 | c.RouteTemplate = "swagger/{documentName}/swagger.json"; 339 | } 340 | }); 341 | // 加载swagger-ui 资源 (HTML, JS, CSS etc.) 342 | app.UseSwaggerUI(options => 343 | { 344 | foreach (var doc in docConfigInfo.SwaggerDocInfos) 345 | { 346 | options.SwaggerEndpoint($"/swagger/{doc.GroupName ?? doc.Version}/swagger.json", doc.Title ?? "App API V1"); 347 | } 348 | 349 | //允许通过嵌入式资源配置首页 350 | if (!string.IsNullOrWhiteSpace(docConfigInfo.ManifestResourceUrl) && !string.IsNullOrWhiteSpace(docConfigInfo.ManifestResourceAssembly)) 351 | { 352 | var resStream = Assembly.Load(docConfigInfo.ManifestResourceAssembly) 353 | .GetManifestResourceStream(docConfigInfo.ManifestResourceUrl); 354 | if (resStream == null) 355 | { 356 | throw new Exception($"{docConfigInfo.ManifestResourceUrl} 不存在,请检查!"); 357 | } 358 | options.IndexStream = () => resStream; 359 | } 360 | 361 | setupAction?.Invoke(options, docConfigInfo); 362 | }); 363 | 364 | 365 | } 366 | 367 | /// 368 | /// https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/752#issuecomment-467817189 369 | /// When Swashbuckle.AspNetCore 5.0 is released, we can remove it. 370 | /// 371 | /// 372 | public static void CustomDefaultSchemaIdSelector(this SwaggerGenOptions options) 373 | { 374 | string SchemaIdSelector(Type modelType) 375 | { 376 | if (!modelType.IsConstructedGenericType) 377 | { 378 | return modelType.Name; 379 | } 380 | 381 | var prefix = modelType.GetGenericArguments() 382 | .Select(SchemaIdSelector) 383 | .Aggregate((previous, current) => previous + current); 384 | 385 | return modelType.Name.Split('`').First() + "Of" + prefix; 386 | } 387 | 388 | options.CustomSchemaIds(SchemaIdSelector); 389 | } 390 | } 391 | } 392 | --------------------------------------------------------------------------------