zoukankan      html  css  js  c++  java
  • 插件式WebApi服务及自动生成Api帮助文档

    上一篇博客中,讲到了将WebApi Host到控制台和IIS,本篇总结一下如何将WebApi的Service以插件的形式进行动态部署,并设置Hoster的首页显示Api帮助文档,当然,也包括动态部署进来的插件的Api帮助。


    话不多说,上酸菜,啊不, 上干货。

    源码地址

    1. 建立Host
      新建 Asp.Net Web Application, 解决方案名称填写WeiApiPluginDemo,项目名称填写IISHost,确定

    选择 Empty, 确定

    菜单中点选 Tools -> NuGet Package Manager -> Package Manager Console
    控制台中输入

    Install-Package Microsoft.AspNet.WebApi.HelpPage
    

    将会在IISHost项目中增加Area目录以及目录下的一大坨目录和文件,暂且放下不管,等会我们再来配置和编码。

    鼠标右键点击IISHost项目,Add -> Global Application Class, 建立全局配置文件, 在弹出的 Specify Name for Item 窗体中点击 OK, 使用默认的 Item name

    Global.asax.cs 中, 删掉除 Application_Start 外的其他方法(这里用不到)

    添加代码如下:

          protected void Application_Start(object sender, EventArgs e)
          {
                AreaRegistration.RegisterAllAreas();
                GlobalConfiguration.Configure(WebApiConfig.Register);
                RouteConfig.RegisterRoutes(RouteTable.Routes);
          }    
    
     鼠标右键点击IISHost项目,*Add -> New Folder*, 建立名为 *App_Start* 的目录,右键点击新建的目录,*Add->Class*, 新建名为 *RouteConfig.cs* 的类.
    
     最终代码如下, 注意添加相关引用。
     ```csharp
    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );
        }
    }
     ```
    
     鼠标右键点击 *App_Start* 目录,*Add->Class*, 新建名为 *WebApiConfig.cs* 的类,添加 *Register* 方法
     ```csharp
        public static void Register(HttpConfiguration config)
        {
            config.Services.Replace(typeof(IAssembliesResolver), new PluginsAssembliesResolver());
    
            config.MapHttpAttributeRoutes();
    
            config.EnableCors();
    
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
             );
        }
     ```
    

    在项目根目录中新建一个名为 WebSettingsConfig 的辅助类

        public class WebSettingsConfig
        {
            public static string plugin_location
            {
                get
                {
                    return AppSettingValue();
                }
            }
    
            private static string AppSettingValue([CallerMemberName] string key = null)
            {
                return ConfigurationManager.AppSettings[key];
            }
        }
    

    web.config 配置, 确保 bin/plugins 目录存在,这个目录是将来我们存放插件的地方

       <configuration>
         <appSettings>
         <!--插件目录-->
         <add key="plugin_location" value="~/bin/plugins"/>
         </appSettings>
         ...
    

    回到 Global.asax.cs, 添加对 RouteConfig 的命名空间引用

    右键点击 App_Start 目录,新建名为 PluginsAssembliesResolver 的类,该类负责解析插件(dll)

    代码如下:

          ```csharp
        /// <summary>
        /// 发现非引用Dll中的Controller,意即插件
        /// </summary>
        public class PluginsAssembliesResolver : DefaultAssembliesResolver
        {
            public virtual ICollection<Assembly> GetAssemblies()
            {
                ICollection<Assembly> baseAssemblies = base.GetAssemblies();
                var mp = HttpContext.Current.Server.MapPath(WebSettingsConfig.plugin_location);
    
                foreach (string file in Directory.GetFiles(mp, "*.dll"))
                {
                    var controllersAssembly = Assembly.LoadFile(file);
                    baseAssemblies.Add(controllersAssembly);
                }
    
                List<Assembly> assemblies = new List<Assembly>(baseAssemblies);
                return assemblies;
    
            }
        }
    

    鼠标右键点击 IISHost 项目,Add -> New Folder, 建立名为 Controllers 的目录,右键点击新建的目录,Add -> Controller...,在弹出的 Add Scaffold 窗体中选择 MVC5 Controller * Empty,点击 Add,在 Add Controller 窗体将新的 Controller 命名为 HomeController

    替换 HomeController.cs 中的 Index() 内容,最后代码长这样

         public class HomeController : Controller
         {
            // GET: Home
            public ActionResult Index()
            {
                return RedirectToAction("Index", "Help"); //替换原来的 return View();
            }
         }
    

    删掉系统自动创建的 Views 目录

    打开 IISHost 项目中的 Areas->HelpPage->App_Start->HelpPageConfig.cs, 在 Register 方法中添加如下代码

         public static void Register(HttpConfiguration config)
         {
            //添加
            config.SetDocumentationProvider(new MultiXmlDocumentationProvider(HttpContext.Current.Server.MapPath(WebSettingsConfig.plugin_location)));
         }
    
    

    HelpPageConfig.cs 的上一级目录下(也就是HelpPage目录下)新建名为 MultiXmlDocumentationProvider.cs 的 class

    该类实现 IDocumentationProvider, IModelDocumentationProvider 两个接口,具体代码如下:

        public class MultiXmlDocumentationProvider : IDocumentationProvider, IModelDocumentationProvider
        {
            //说白了就是查找目录下的所有Xml文档,加载到 _documentationProviders 中
            private IList<XmlDocumentationProvider> _documentationProviders;
    
            public MultiXmlDocumentationProvider(string xmlDocFilesPath)
            {
                _documentationProviders = new List<XmlDocumentationProvider>();
    
                foreach (string file in Directory.GetFiles(xmlDocFilesPath, "*.xml"))
                {
                    _documentationProviders.Add(new XmlDocumentationProvider(file));
                }
            }
    
            public string GetDocumentation(HttpParameterDescriptor parameterDescriptor)
            {
                return _documentationProviders.Select(x => x.GetDocumentation(parameterDescriptor)).FirstOrDefault(x => !string.IsNullOrEmpty(x));
            }
    
            public string GetDocumentation(Type type)
            {
                return _documentationProviders.Select(x => x.GetDocumentation(type)).FirstOrDefault(x => !string.IsNullOrEmpty(x));
            }
    
            //成员导航
            public string GetDocumentation(MemberInfo member)
            {
                return _documentationProviders
              .Select(x => x.GetDocumentation(member))
              .FirstOrDefault(x => !string.IsNullOrWhiteSpace(x));
            }
    
            //action 描述
            public string GetDocumentation(HttpActionDescriptor actionDescriptor)
            {
                return _documentationProviders.Select(x => x.GetDocumentation(actionDescriptor)).FirstOrDefault(x => !string.IsNullOrEmpty(x));
            }
    
            //Controller 描述
            public string GetDocumentation(HttpControllerDescriptor controllerDescriptor)
            {
                return _documentationProviders.Select(x => x.GetDocumentation(controllerDescriptor)).FirstOrDefault(x => !string.IsNullOrEmpty(x));
            }
    
            public string GetResponseDocumentation(HttpActionDescriptor actionDescriptor)
            {
                return _documentationProviders.Select(x => x.GetDocumentation(actionDescriptor)).FirstOrDefault(x => !string.IsNullOrEmpty(x));
    
            }
        }
    

    编译项目 IISHost 确保没有错误

    1. 建立类库项目若干

    右键点击解决方案, 新建类库,命名为 DemoClass01

    菜单中点选 Tools -> NuGet Package Manager -> Package Manager Console
    控制台中输入

        Install-Package Microsoft.AspNet.WebApi.Core
    

    在项目 DemoClass01 中新建目录 Controllers 并新建 Controllers\DemoClass01.cs, 代码如下:

        /// <summary>
        /// 测试DemoClass01
        /// </summary>
        [RoutePrefix("demo")]
        public class DemoController : ApiController
        {
            /// <summary>
            /// 测试方法1
            /// </summary>
            /// <returns></returns>
            [HttpGet, Route("get1")]
            public HttpResponseMessage Get()
            {
                return Request.CreateResponse("demo class 01 response");
            }
        }    
    
    

    右键单击项目 Properties->Build 勾选 XML documentation file 项。

    如法炮制,可以多建立几个类似的项目供测试。

    1. 测试

    发布或者直接使用IISExpress运行(确保插件目录已存在,并将步骤2中的类库生成的Dll文件和Xml文件拷贝至插件目录)

    测试结果如下:

    源码地址

  • 相关阅读:
    2020下第八周总结
    《程序员的自我修养》——阅读感悟1
    2020下第七周总结
    【基础组件11】hdfs与hbase
    【基础组件10】hadoop拓展(三)NameNode工作机制
    【基础组件9】hadoop入门(二)启动节点、集群、hdfs查看文件系统、清数据
    【基础组件8】hadoop入门(一)集群搭建/ HDFS-HA高可用搭建
    【基础组件7】flink入门(一)集群搭建、实时数据处理
    【基础组件6】kafkamanager安装部署+详细参数讲解+使用教程
    【基础组件5】kafka入门(一)集群搭建+常用命令+基本原理+存储分析
  • 原文地址:https://www.cnblogs.com/zanpen2000/p/6378462.html
Copyright © 2011-2022 走看看