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)]

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

原文地址:https://www.cnblogs.com/Sea1ee/p/10979944.html