本文使用特性来描述接口而不是xml文件,使用特性可自定义接口在swaggerUI上的描述
安装nuget包:Swashbuckle.AspNetCore.SwaggerUI
和
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.OpenApi.Models; namespace swaggerweb { public class Startup { private readonly string swaggerDocName = "weather"; public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddSwaggerGen(opt => { opt.SwaggerDoc(swaggerDocName, new OpenApiInfo() { Version = "v1", Title = "WeatherForecast", Description = "天气预报" }); // 使用annotation来描述接口,不依赖XML文件 opt.EnableAnnotations(); // 下面两句,将swagger文档中controller名使用GroupName替换 // 在Swagger中,一个Tag可以看作是一个API分组 opt.DocInclusionPredicate((_, apiDescription) => string.IsNullOrWhiteSpace(apiDescription.GroupName) == false); opt.SwaggerGeneratorOptions.TagsSelector = (apiDescription) => new[] { apiDescription.GroupName }; }); services.AddControllers(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseSwagger(opt => { // 相对路径加载swagger文档 //opt.RouteTemplate = "swagger/{documentName}"; }) .UseSwaggerUI(opt => { opt.SwaggerEndpoint($"{swaggerDocName}/swagger.json", "天气预报API文档"); }); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); // 也可以在这里配置swagger文档路径 //endpoints.MapSwagger(); }); } } }
Controller和Action上使用特性:ApiExplorerSettings
和SwaggerOperation
:
using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Swashbuckle.AspNetCore.Annotations; using System; using System.Collections.Generic; using System.Linq; namespace swaggerweb.Controllers { [ApiExplorerSettings(GroupName = "天气预报")] [Route("[controller]")] public class WeatherForecastController : ControllerBase { private static readonly string[] Summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" }; private readonly ILogger<WeatherForecastController> _logger; public WeatherForecastController(ILogger<WeatherForecastController> logger) { _logger = logger; } [HttpGet] [SwaggerOperation(Summary = "获取天气预报信息")] public IEnumerable<WeatherForecast> Get() { var rng = new Random(); return Enumerable.Range(1, 5).Select(index => new WeatherForecast { Date = DateTime.Now.AddDays(index), TemperatureC = rng.Next(-20, 55), Summary = Summaries[rng.Next(Summaries.Length)] }) .ToArray(); } } }
效果图:
2020-07-28 补充
1. 默认折叠swagger 文档
当接口比较多时,展开Tag看起来比较费力,这里折叠下
public void Configure(IApplicationBuilder app, IHostEnvironment env) { app.UseSwagger().UseSwaggerUI(opt => { // 折叠所有的Tag opt.DocExpansion(DocExpansion.None); // 隐藏API中定义的model opt.DefaultModelsExpandDepth(-1); }); }
2. 添加Authorization请求头
有些接口需要认证/授权,这里针对ASP.NET Core中在Controller上标记Authorize特性的情况,使用swagger中的自定义Filter来实现在swagger界面上发起请求时传递授权token
public void ConfigureServices(IServiceCollection services) { services.AddSwaggerGen(opt => { opt.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme() { Scheme = "bearer", BearerFormat = "JWT", Description = "JWT Authorization header using the Bearer scheme. Example: "Authorization: Bearer {token}"", Name = "Authorization", In = ParameterLocation.Header, Type = SecuritySchemeType.Http }); opt.OperationFilter<AuthenticationOperationFilter>(); }); }
自定义过滤器:
public class AuthenticationOperationFilter : IOperationFilter { public void Apply(OpenApiOperation operation, OperationFilterContext context) { var actionScopes = context.MethodInfo.GetCustomAttributes(true).OfType<AuthorizeAttribute>().Select(attr => attr.TypeId.ToString()).Distinct(); var controllerScopes = context.MethodInfo.DeclaringType!.GetCustomAttributes(true) .Union(context.MethodInfo.GetCustomAttributes(true)) .OfType<AuthorizeAttribute>() .Select(attr => attr.TypeId.ToString()); var requiredScopes = actionScopes.Union(controllerScopes).Distinct().ToArray(); if (requiredScopes.Any()) { operation.Responses.Add("401", new OpenApiResponse { Description = "Unauthorized" }); operation.Responses.Add("419", new OpenApiResponse { Description = "AuthenticationTimeout" }); operation.Responses.Add("403", new OpenApiResponse { Description = "Forbidden" }); var oAuthScheme = new OpenApiSecurityScheme { Scheme = "Bearer", Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" } }; operation.Security = new List<OpenApiSecurityRequirement> { new OpenApiSecurityRequirement { [ oAuthScheme ] = new List<string>() } }; } } }
swagger界面上,每个API及swagger顶部均会出现小锁,点击小锁可以输入token:
3. 序列化问题
发现API中若定义了IDictionary<,>类型的字段,swagger默认的序列化方式会出错,这里使用Newtonsoft来序列化。需要安装nuget包:Swashbuckle.AspNetCore.Newtonsoft:
public void ConfigureServices(IServiceCollection services) { services.AddSwaggerGen().AddSwaggerGenNewtonsoftSupport(); }