• Net6 扩展你的Swagger,让它变的更强大,更持久(哈哈哈)


    十年河东,十年河西,莫欺少年穷

    学无止境,精益求精

    net6集成了swagger的基础功能,功能不够用

    因此只能自定义扩展方法了,

    1、集成Jwt授权

     将

    builder.Services.AddSwaggerGen();

    改成

    builder.Services.AddSwaggerGen(c =>
    { 
        var scheme = new OpenApiSecurityScheme()
        {
            Description = "Authorization header. \r\nExample: 'Bearer abcdefxxx'",
            Reference = new OpenApiReference
            {
                Type = ReferenceType.SecurityScheme,
                Id = "Authorization"
            },
            Scheme = "oauth2",
            Name = "Authorization",
            In = ParameterLocation.Header,
            Type = SecuritySchemeType.ApiKey,  
        };
        c.AddSecurityDefinition("Authorization", scheme);
        var requirement = new OpenApiSecurityRequirement();
        requirement[scheme] = new List<string>();
        c.AddSecurityRequirement(requirement); 
    });

    2、增加Swagger注释

    增加swagger注释后,测试人员/前段开发人员就可以自己看文档了,省的在开发人员面前叽叽歪歪

    2.1、设置Model层和Api层项目XML输出

     代码如下:

    builder.Services.AddSwaggerGen(c =>
    {
        var basePath = Path.GetDirectoryName(AppContext.BaseDirectory);
        //c.IncludeXmlComments(Path.Combine(basePath, Assembly.GetExecutingAssembly().GetName().Name+".xml"), true);
        c.IncludeXmlComments(Path.Combine(basePath, "swap.xml"), true);
        c.IncludeXmlComments(Path.Combine(basePath, "swapModels.xml"), true);
    
        //
        var scheme = new OpenApiSecurityScheme()
        {
            Description = "Authorization header. \r\nExample: 'Bearer 12345abcdef'",
            Reference = new OpenApiReference
            {
                Type = ReferenceType.SecurityScheme,
                Id = "Authorization"
            },
            Scheme = "oauth2",
            Name = "Authorization",
            In = ParameterLocation.Header,
            Type = SecuritySchemeType.ApiKey,  
        };
        c.AddSecurityDefinition("Authorization", scheme);
        var requirement = new OpenApiSecurityRequirement();
        requirement[scheme] = new List<string>();
        c.AddSecurityRequirement(requirement); 
    });
    View Code

    3、自定义属性隐藏及Api方法隐藏

    3.1、Api层新建swagger过滤器

    using Microsoft.OpenApi.Models;
    using swapCommon;//HiddenFieldAttribute 和 HiddenAttribute 在公共类库存 
    using Swashbuckle.AspNetCore.SwaggerGen;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net.Http;
    using System.Reflection;
    using System.Text; 
    
    namespace swapInit
    { 
        public class HiddenApiFilter : IDocumentFilter
        {
            public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
            {
                foreach (var item in context.ApiDescriptions)
                {
                    if (item.TryGetMethodInfo(out MethodInfo methodInfo))
                    {
                        if (methodInfo.ReflectedType.CustomAttributes.Any(t => t.AttributeType == typeof(HiddenAttribute))
                        || methodInfo.CustomAttributes.Any(t => t.AttributeType == typeof(HiddenAttribute)))
                        {
                            var key = "/" + item.RelativePath.TrimEnd('/');
                            if (key.Contains("?"))
                            {
                                int idx = key.IndexOf("?", StringComparison.Ordinal);
                                key = key.Substring(0, idx);
                            }
                            if (swaggerDoc.Paths.ContainsKey(key))
                            {
                                swaggerDoc.Paths.Remove(key);
                            }
                        }
                    }
                }
            }
        }
    
    
        public class HiddenFieldFilter : ISchemaFilter
        {
            public void Apply(OpenApiSchema schema, SchemaFilterContext context)
            {
                if (schema?.Properties == null)
                {
                    return;
                }
                var name = context.Type.FullName;
                var excludedProperties = context.Type.GetProperties();
                foreach (var property in excludedProperties)
                {
                    var attribute = property.GetCustomAttribute<HiddenFieldAttribute>();
                    if (attribute != null
                        && schema.Properties.ContainsKey(ToLowerStart(property.Name)))
                    {
                        schema.Properties.Remove(ToLowerStart(property.Name));
                    }
                };
            }
            public static string ToLowerStart( string source)
            {
                if (string.IsNullOrWhiteSpace(source))
                {
                    return source;
                }
                var start = source.Substring(0, 1);
                return $"{start.ToLower()}{source.Substring(1, source.Length - 1)}";
            }
        } 
    }
    View Code

    3.2、公共类库层新建属性类

    using System;
    using System.Collections.Generic;
    using System.Text;
    
    namespace swapCommon
    {
        [AttributeUsage(AttributeTargets.Property)]
        public class HiddenFieldAttribute : Attribute
        {
        }
    
        [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
        public class HiddenAttribute : Attribute
        {
        }
    }

    3.3、引用上述过滤器

    builder.Services.AddSwaggerGen(c =>
    {
        var basePath = Path.GetDirectoryName(AppContext.BaseDirectory);
        //c.IncludeXmlComments(Path.Combine(basePath, Assembly.GetExecutingAssembly().GetName().Name+".xml"), true);
        c.IncludeXmlComments(Path.Combine(basePath, "swap.xml"), true);
        c.IncludeXmlComments(Path.Combine(basePath, "swapModels.xml"), true);
        //
        c.DocumentFilter<HiddenApiFilter>(); 
        c.SchemaFilter<HiddenFieldFilter>();
        //
        var scheme = new OpenApiSecurityScheme()
        {
            Description = "Authorization header. \r\nExample: 'Bearer 12345abcdef'",
            Reference = new OpenApiReference
            {
                Type = ReferenceType.SecurityScheme,
                Id = "Authorization"
            },
            Scheme = "oauth2",
            Name = "Authorization",
            In = ParameterLocation.Header,
            Type = SecuritySchemeType.ApiKey,  
        };
        c.AddSecurityDefinition("Authorization", scheme);
        var requirement = new OpenApiSecurityRequirement();
        requirement[scheme] = new List<string>();
        c.AddSecurityRequirement(requirement); 
    });
    View Code

    3.4、测试Swagger过滤器

    3.4.1、定义一个Post方法

            /// <summary>
            /// 演示字段隐藏
            /// </summary>
            /// <param name="stdto"></param>
            /// <returns></returns>
            [HttpPost]
            [Route("GetStdto")] 
            public IActionResult GetStdto([FromBody]stdto stdto)
            {
                var dt = DateTime.Now;
                return Ok(dt );
            }

    3.4.2、定义参数实体

    有了身份证号,可以自动计算出年龄等场景,总之不想让测试和前端人员看到,省的他们叽叽歪歪

        public class stdto
        {
            public string name { get; set; }
            public string IdCard { get; set; }
            /// <summary>
            /// 该字段会在swagger中隐藏
            /// </summary>
            [HiddenField]
            public int age { get; set; }
        }

     3.5、[Hidden]隐藏 Action 方法

    不想让测试或前端在swagger上看到某方法,那就隐藏,省的他们叽叽歪歪

            /// <summary>
            /// 演示Api隐藏 ,该方法不会展示在swagger上
            /// </summary>
            /// <param name="Hs">https://www.cnblogs.com/catcher1994/p/responsecaching.html</param>
            /// <returns></returns>
            [HttpGet]
            [Hidden]
            [Route("GetTime")] 
            public IActionResult GetTime()
            {
                var dt = DateTime.Now;
                return Ok(dt);
            }

    不作截图演示了。

    4、规定项目时间返回格式

    严格来说这个和swagger没关,...分享是一种美德

    4.1、公共类库层先建JsonResult格式化类

     using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Text.Json; 
    using System.Text.Json.Serialization;
    
    namespace swapCommon.Ext
    {
        public class JsonOptionsExt : JsonConverter<DateTime>
        {
            private readonly string Format;
            public JsonOptionsExt(string format = "yyyy-MM-dd HH:mm:ss")
            {
                Format = format;
            }
            public override void Write(Utf8JsonWriter writer, DateTime date, JsonSerializerOptions options)
            {
                writer.WriteStringValue(date.ToString(Format));
            }
            public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
            {
                // 获取时间类型的字符串
                var dt = reader.GetString();
                if (!string.IsNullOrEmpty(dt))
                {
                    //将日期与时间之间的"T"替换为一个空格,将结尾的"Z"去掉,否则会报错
                    dt = dt.Replace("T", " ").Replace("Z", "");
                    //取到秒,毫秒内容也要去掉,经过测试,不去掉会报错
                    if (dt.Length > 19)
                    {
                        dt = dt.Substring(0, 19);
                    }
                    return DateTime.ParseExact(dt, Format, null);
                }
                return DateTime.Now;
            }
        }
    }
    View Code

    4.2、添加控制器时引用

    builder.Services.AddControllers()

    改成

    builder.Services.AddControllers().AddJsonOptions(options =>
    {
        //时间格式化响应
        options.JsonSerializerOptions.Converters.Add(new JsonOptionsExt());
    }); 

    改好后,时间的返回就统一了

     ok,截止到这儿,就over了,希望前端和测试不要骂我。 

    2022年12月5日补充如下:

    关于时间格式为  "yyyy-MM-dd HH:mm:ss" 也可以不使用自定义的JsonOptionsExt

    添加Nutget引用,Microsoft.AspNetCore.Mvc.NewtonsoftJson V6.0.6

    AddControllers()代码段替换为:

    builder.Services.AddControllers().AddNewtonsoftJson(options =>
    {
        options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
        options.SerializerSettings.ContractResolver = new DefaultContractResolver();
    }); 

    其中

    options.SerializerSettings.ContractResolver = new DefaultContractResolver(); /*支持接收JOBject动态参数*/

    JOBject 动态参数,例如

            [AllowAnonymous]
            [HttpPost]
            [Route("TestAlter")]
            public IActionResult TestAlter([FromBody] JObject data)
            { 
                return Ok(data);
            } 

    可接受任意json

    @天才卧龙

  • 相关阅读:
    SEO值得学习建议
    ClientValidationFunction
    readystate的五种状态
    XMLHTTP对象参考
    Provider详解
    有缺点,向左走向右走
    DotNetBar 6.6.0.4 for Vs2005 (+特殊补丁)
    [无敌]一些web开发中常用的、做成cs文件的js代码 转帖来的
    AjaxPro.NET框架生成高效率的Tree(Asp.net 2.0)(示例代码下载)
    Vista 下使用Visual Studio 2005 开发Oracle 方面程序出现的数据连结问题及解决方案
  • 原文地址:https://www.cnblogs.com/chenwolong/p/swger.html
Copyright © 2020-2023  润新知