• webapi+swagger ui 文档描述


    代码:GitHub

    swagger ui在我们的.NET CORE和.NET Framework中的展现形式是不一样的,如果有了解的,在.NET CORE中的是比.NET Framework好的。两张图对比下

     .NET Framework中自带的就是这个,样式一般

    .NET CORE中:

     一对比core中的明显好看,本篇教你怎么在Framework 环境中搭建下面的样式,先看看效果,下面就是在Framework 环境搭建的效果:

     

    环境:Owin

    owin了解:https://www.cnblogs.com/neverc/p/4864414.html

     注:怎么搭建的可以百度一下Owin,这边主要是介绍要注意的几点,源码在github上。

    ①下载我们的Swagger ui

    地址:https://github.com/swagger-api/swagger-ui

    下载dist文件夹的东西

    添加到我们的项目中,文件夹为swagger

     ② nuget  Swashbuckle.Core

    在App_Start中创建一个DocConfig 类,进行文档配置

    using Sealee.Util;
    using Swashbuckle.Application;
    using Swashbuckle.Swagger;
    using System;
    using System.Collections.Concurrent;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using System.Web;
    using System.Web.Http;
    using System.Web.Http.Description;
    using System.Xml;
    using WebApiOwin.App_Start;
    
    namespace WebApiOwin
    {
        public class DocConfig
        {
            public static void Register(HttpConfiguration config)
            {
                Assembly _thisAssembly = typeof(DocConfig).Assembly;
                string _project = MethodBase.GetCurrentMethod().DeclaringType.Namespace;//项目命名空间
    
                //注释  我们的post提交都会创建Dto来申明,这边添加了注释,前台页面就会显示
                string path = System.AppDomain.CurrentDomain.BaseDirectory;
                string _xmlPath = string.Format("{0}/bin/{1}.XML", path, _project);
                string path2 = path.GetSlnPath(2);
                string _xmlPath2 = Path.Combine(path2, "My.Entity\bin\My.Entity.xml");
    
    
                config.EnableSwagger(c =>
                {
                    c.MultipleApiVersions(
                          (apiDesc, targetApiVersion) =>
                          {
                              //控制器描述
                              IEnumerable<string> versions = apiDesc.ActionDescriptor.ControllerDescriptor.GetCustomAttributes<MyVersionAttribute>().Select(x => x.Version);
                              return versions.Any(v => $"{v.ToString()}" == targetApiVersion);
                          },
                          (vc) =>
                          {
                              //MyVersionAttribute 标识了这个属性的都需要在这里加上  这边会配合index.html页面完成
                              vc.Version("Token", "");
                              vc.Version("JwtUser", "");
                          });
    
                    //c.SingleApiVersion("Token", "Super duper API");
                    //忽略标记为已删除的属性
                    c.IgnoreObsoleteProperties();
    
                    //多文档描述
                    //文档描述
                    c.IncludeXmlComments(_xmlPath);
                    //文档描述
                    c.IncludeXmlComments(_xmlPath2);
    
                    c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
    
                    c.CustomProvider((defaultProvider) =>
                    {
                        //获取描述
                        return new MySwaggerProvider(defaultProvider, _xmlPath);
                    });
    
                    //操作过滤
                    c.OperationFilter<HttpHeadFilter>();
                }); //.EnableSwaggerUi()  重点:这边我们不需要他生成页面,使用我们刚刚下载dist中的页面
    
            }
        }
    
        /// <summary>
        /// 设置SwaggerDocument 显示的数据
        /// </summary>
        public class MySwaggerProvider : ISwaggerProvider
        {
            private static ConcurrentDictionary<string, SwaggerDocument> _cache =
                   new ConcurrentDictionary<string, SwaggerDocument>();
    
            private readonly ISwaggerProvider _swaggerProvider;
            private readonly string _xmlPath;
    
            public MySwaggerProvider(ISwaggerProvider swaggerProvider, string xmlPath)
            {
                _swaggerProvider = swaggerProvider;
                _xmlPath = xmlPath;
            }
    
            public SwaggerDocument GetSwagger(string rootUrl, string apiVersion)
            {
                string cacheKey = string.Format("{0}_{1}", rootUrl, apiVersion);
                //只读取一次
                if (!_cache.TryGetValue(cacheKey, out SwaggerDocument srcDoc))
                {
                    srcDoc = _swaggerProvider.GetSwagger(rootUrl, apiVersion);
                    ConcurrentDictionary<string, string> pairs = GetControllerDesc(apiVersion);
                    //控制器描述
                    IList<Tag> tagList = new List<Tag>();
                    foreach (KeyValuePair<string, string> item in pairs)
                    {
                        Tag tag = new Tag();
                        tag.name = item.Key;
                        tag.description = item.Value;
                        tagList.Add(tag);
                    }
                    srcDoc.tags = tagList;
    
    
                    srcDoc.vendorExtensions = new Dictionary<string, object> {
                            { "ControllerDesc", pairs }
                        };
                    _cache.TryAdd(cacheKey, srcDoc);
                }
                return srcDoc;
            }
    
            /// <summary>
            /// 从API文档中读取控制器描述
            /// </summary>
            private ConcurrentDictionary<string, string> GetControllerDesc(string apiVersion)
            {
                ConcurrentDictionary<string, string> controllerDescDict = new ConcurrentDictionary<string, string>();
                if (File.Exists(_xmlPath))
                {
                    XmlDocument xmldoc = new XmlDocument();
                    xmldoc.Load(_xmlPath);
                    string type = string.Empty, path = string.Empty, controllerName = string.Empty;
    
                    string[] arrPath;
                    int length = -1, cCount = "Controller".Length;
                    XmlNode summaryNode = null;
                    foreach (XmlNode node in xmldoc.SelectNodes("//member"))
                    {
                        type = node.Attributes["name"].Value;
                        if (type.StartsWith("T:"))
                        {
                            string[] typeName = type.Split(':');
                            Type t = Type.GetType(typeName[1]);
    
                            //控制器
                            arrPath = type.Split('.');
                            length = arrPath.Length;
                            controllerName = arrPath[length - 1];
                            if (controllerName.EndsWith("Controller"))
                            {
                                //如果分组了
                                if (t.GetCustomAttributes<MyVersionAttribute>().Count() != 0)
                                {
                                    string version = t.GetCustomAttribute<MyVersionAttribute>().Version;
                                    //上面tag和下面的需要同步过滤
                                    if (version == apiVersion)
                                    {
                                        //获取控制器注释
                                        summaryNode = node.SelectSingleNode("summary");
                                        string key = controllerName.Remove(controllerName.Length - cCount, cCount);
                                        if (summaryNode != null && !string.IsNullOrEmpty(summaryNode.InnerText) && !controllerDescDict.ContainsKey(key))
                                        {
                                            controllerDescDict.TryAdd(key, summaryNode.InnerText.Trim());
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                return controllerDescDict;
            }
        }
    
    
        public class HttpHeadFilter : IOperationFilter
        {
            public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
            {
                // if (operation.parameters == null)
                //     operation.parameters = new List<Parameter>();
                ////判断是否添加授权过滤器
                // var filterPipeline = apiDescription.ActionDescriptor.GetFilterPipeline();
                // var isAuthorized = filterPipeline.Select(fileInfo => fileInfo.Instance).Any(filter => filter is IAuthorizationFilter);
                // var allowAnonymous = apiDescription.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any();
                // if (isAuthorized&&!allowAnonymous)
                // {
                //     operation.parameters.Add(new Parameter { name = "Authorization", @in = "head", description = "token", required = false, type = "string" });
    
                // }                                                         
    
                if (operation == null)
                {
                    return;
                }
    
                if (operation.parameters == null)
                {
                    operation.parameters = new List<Parameter>();
                }
                if (operation.security == null)
                {
                    operation.security = new List<IDictionary<string, IEnumerable<string>>>();
                }
    
                Parameter parameter = new Parameter
                {
                    description = "The authorization token",
                    @in = "header",
                    name = "Authorization",
                    required = true,
                    type = "string"
                };
    
    
                //var parameter = new Parameter
                //{
                //    description = "The authorization token",
                //    @in = "header",
                //    name = "Authorization",
                //    required = true,
                //    type = "string"
                //};                            
                //显示锁标识
                if (apiDescription.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any())
                {
                    //parameter.required = false;
                }
                else
                {
                    Dictionary<string, IEnumerable<string>> oAuthRequirements = new Dictionary<string, IEnumerable<string>> { { "Authorization", new List<string>() } };
                    operation.security.Add(oAuthRequirements);
                }
                // operation.parameters.Add(parameter);    
            }
        }
    }
    View Code
    MyVersionAttribute 类用来显示我们的版本
        [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true)]
        public class MyVersionAttribute : Attribute
        {
    
            public MyVersionAttribute(string _version)
            {
                this.Version = _version;
            }
    
            /// <summary>
            /// 版本
            /// </summary>
            public string Version { get; set; }
        }

     最后在我们的owin中添加DocConfig 

    接口列子:

     

     ③修改我们的Index.html页面

    文档配置:https://github.com/swagger-api/swagger-ui/blob/master/docs/usage/configuration.md

     附授权,页面上左边的按钮:

    地址: https://github.com/aspnetboilerplate/eventcloud/blob/master/aspnet-core-angular/aspnet-core/src/EventCloud.Web.Host/wwwroot/swagger/ui/index.html

    得到这两个js,应用到你的项目

     这边就是这两个js生成了授权按钮,以及样式,文本,然后把你授权需要的信息传到后台进行获取token。看下这个js你就知道了,这边不详细介绍了.应为项目中的授权不一样这边的代码你也进行相应的修改才行,别直接Copy用。

    授权:一般我们的在接口中授权了的需要你携带token信息才能访问。

     

     

    隐藏接口:

      [ApiExplorerSettings(IgnoreApi = true)]

     总结:最主要的还是不要使用代码生成的页面,需要我们的自己添加的页面,然后进行配置就好了。

  • 相关阅读:
    mysql配置图解(mysql 5.5)
    C++中的enum
    vc6.0中的dsp,dsw,ncb,opt,clw,plg,aps等文件的简单说明
    using namespace std
    C#中Cache的使用 迎客
    数据库里的存储过程和事务有什么区别? 迎客
    WINDOWS远程默认端口3389的正确修改方式 迎客
    DES加密和解密PHP,Java,ObjectC统一的方法 迎客
    转:15点 老外聊iPhone游戏开发注意事项 迎客
    windows server 2003 删除默认共享 迎客
  • 原文地址:https://www.cnblogs.com/Sea1ee/p/10979944.html
Copyright © 2020-2023  润新知