asp.net core 3.1/swagger

 

本文使用特性来描述接口而不是xml文件,使用特性可自定义接口在swaggerUI上的描述

安装nuget包:Swashbuckle.AspNetCore.SwaggerUISwashbuckle.AspNetCore.Annotations,配置swagger:

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上使用特性:ApiExplorerSettingsSwaggerOperation

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

 

推荐阅读

Grouping Operations With Tags

posted @ 2020-05-20 11:30  雪飞鸿  阅读(632)  评论(2编辑  收藏  举报