下面就一些web api的一些基础内容进行阐述,然后就web api宿主承载中的实际业务问题进行解决
HttpController
     HttpController的激活是由处于消息处理管道尾端的HttpRoutingDispatcher来完成的,具体来说是HttpRoutingDispatcher利用HttpControllerDispatcher实现了针对目标HttpController的激活和执行。激活目标HttpController的前提是能够正确解析出HttpController的真实类型,而类型解析需要针对加载的程序集,所以我们需要先来了解一个用于解析程序集的对象AssembliesResolver。在ASP.NET Web API的HttpController激活系统中,AssembliesResolver为目标HttpController的类型解析提供候选的程序集。换句话说,候选HttpController类型的选择范围仅限于定义在通过AssembliesResolver提供的程序集中的所有实现了IHttpController接口的类型
AssembliesResolver
     所有的AssembliesResolver均实现了IAssembliesResolver接口。根据程序反射得到如下代码片段,根据代码片段得知,IAssembliesResolver提供的是程序集列表

public interface IAssembliesResolver
{
    ICollection<Assembly> GetAssemblies();
}
   
DefaultAssembliesResolver
     默认的AssembliesResolver为DefaultAssembliesResolver,根据以下代码片段得知,默认返回的是当前应用程序域的程序集

public class DefaultAssembliesResolver : IAssembliesResolver
{
    public virtual ICollection<Assembly> GetAssemblies()
    {
        return AppDomain.CurrentDomain.GetAssemblies().ToList<Assembly>();
    }
}  
 
ServicesContainer
      默认的AssembliesResolver就是通过ServicesContainer类型确定
      Web Api的请求相当于一个管道,类似于流水线作业,每个环节都会注册自己的实现类组件来完成自己的工作。这些组件都会实现自己特定的接口,当然在预置的组件无法满足我们的业务需求时,可以自己来实现组件代码,并进行注册,ServicesContainer其实可以简单的理解为这些组件的一个IOC容器
 
     上面所介绍的就代表着,如果采用selfHost承载web api,而且web api与宿主程序不在同一程序集中的情况,如果在用上篇的代码,将会发现报以下错误  No type was found that matches the controller named 'User'.
    上面所说的情况,分两种,第一种,单个api程序集,多个api程序集
    1.如果api程序集全部写在一个单独的程序集中的情况
    1.1 直接通过Assembly加载外部程序集

        static void Main(string[] args)
        {
            // 如果 API 处于外部程序集,可通过以下代码加载 CM.API为其他程序集
            //Assembly.Load("CM.API, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");    //加载外部程序集
            string baseAddress = "http://localhost:9000/";
            // 启动 OWIN host
            WebApp.Start<Startup>(url: baseAddress);
            Console.WriteLine("程序已启动,按任意键退出");
            Console.ReadLine();
        }

宿主项目还是需要引用CM.API程序集

       1.2通过自定义AssembliesResolber来进行注册      

    public class UserResolver: DefaultAssembliesResolver
    {
        public override ICollection<Assembly> GetAssemblies()
        {
            ICollection<Assembly> baseAssemblies = base.GetAssemblies();
            List<Assembly> assemblies = new List<Assembly>(baseAssemblies);
            var assembly = AppDomain.CurrentDomain.BaseDirectory;
            string path = assembly + "\\" + "CM.API.dll";
            var controllersAssembly = Assembly.LoadFrom(path);
            baseAssemblies.Add(controllersAssembly);
            return assemblies;
        }
    }
         然后宿主启动时进行注册        

        static void Main(string[] args)
        {
            var config = new HttpSelfHostConfiguration("http://localhost:8083");
            config.Routes.MapHttpRoute(
                "API Default", "api/{controller}/{id}",
                new { id = RouteParameter.Optional });
            //注册UserResolver,加载程序集
            config.Services.Replace(typeof(IAssembliesResolver), new UserResolver());
            using (var server = new HttpSelfHostServer(config))
            {
                server.OpenAsync().Wait();
                Console.WriteLine("Press Enter to quit.");
                Console.ReadLine();
            }
        }
      2.当然在业务开发中如果API被分散开发到多个程序集中,这种情况当然根据项目框架区分,各有利弊
      2.1 通过上述的UserServoler进行加载      
    public class UserResolver: DefaultAssembliesResolver
    {
        public override ICollection<Assembly> GetAssemblies()
        {
            ICollection<Assembly> baseAssemblies = base.GetAssemblies();
            List<Assembly> assemblies = new List<Assembly>(baseAssemblies);
            var assembly = AppDomain.CurrentDomain.BaseDirectory;
            string path = assembly + "\\" + "CM.API.dll";
            var controllersAssembly = Assembly.LoadFrom(path);
            baseAssemblies.Add(controllersAssembly);
            //加载多个程序集   不建议写死
            string path2 = assembly + "\\" + "CM.API2.dll";
            var controllersAssembly2 = Assembly.LoadFrom(path2);
            baseAssemblies.Add(controllersAssembly2);
            return assemblies;
        }
    }
       上述代码只是展示加载的一种方式,只是得到程序集的方式需要去进行配置编码,不建议直接写死在代码里
       2.2 通过自定配置类,进行配置文件读取加载
            添加自定义配置类        
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Configuration;
using System.Reflection;

namespace CM.SelfHost
{
    public class AssembliesLoad : ConfigurationSection
    {
        [ConfigurationProperty("", IsDefaultCollection = true)]
        public AssemblyElementCollection AssemblyNames
        {
            get { return (AssemblyElementCollection)this[""]; }
        }

        public static AssembliesLoad GetSection()
        {
            return ConfigurationManager.GetSection("AssembliesLoad") as AssembliesLoad;
        }
    }
    public class AssemblyElementCollection : ConfigurationElementCollection
    {
        protected override ConfigurationElement CreateNewElement()
        {
            return new AssemblyElement();
        }
        protected override object GetElementKey(ConfigurationElement element)
        {
            AssemblyElement serviceTypeElement = (AssemblyElement)element;
            return serviceTypeElement.AssemblyName;
        }
    }

    public class AssemblyElement : ConfigurationElement
    {
        [ConfigurationProperty("assemblyName", IsRequired = true)]
        public string AssemblyName
        {
            get { return (string)this["assemblyName"]; }
            set { this["assemblyName"] = value; }
        }
    }
} 
        添加配置文件,如下,加入ConfigSections节点以及AssembliesLoad节点

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>
  <configSections>
    <section name="AssembliesLoad" type="CM.SelfHost.AssembliesLoad,CM.SelfHost"/>
  </configSections>
  <AssembliesLoad>
    <add assemblyName="CM.API.dll" />
  </AssembliesLoad>
</configuration>
       添加AssemblyResolver类,并注册

    public class WebApiResolver: DefaultAssembliesResolver
    {
        public override ICollection<Assembly> GetAssemblies()
        {
            AssembliesLoad settings = AssembliesLoad.GetSection();
            if (null != settings)
            {
                foreach (AssemblyElement element in settings.AssemblyNames)
                {
                    AssemblyName assemblyName = AssemblyName.GetAssemblyName(element.AssemblyName);
                    if (!AppDomain.CurrentDomain.GetAssemblies().Any(assembly =>
                        AssemblyName.ReferenceMatchesDefinition(assembly.GetName(), assemblyName)))
                    {
                        AppDomain.CurrentDomain.Load(assemblyName);
                    }
                }
            }
            return base.GetAssemblies();
        }
    }
      注册Resolver        
        static void Main(string[] args)
        {
            //Assembly.Load("CM.API, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");    //加载外部程序集
            var config = new HttpSelfHostConfiguration("http://localhost:8083");
            config.Routes.MapHttpRoute(
                "API Default", "api/{controller}/{id}",
                new { id = RouteParameter.Optional });
            config.Services.Replace(typeof(IAssembliesResolver), new UserResolver());
            using (var server = new HttpSelfHostServer(config))
            {
                server.OpenAsync().Wait();
                Console.WriteLine("Press Enter to quit.");
                Console.ReadLine();
            }
        }
      运行会报错 其他信息: 配置系统未能初始化
      查阅一些说明之后发现,如果存在自定义配置ConfigSections节点,那么必须在第一个节点,修改app.confg如下

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="AssembliesLoad" type="CM.SelfHost.AssembliesLoad,CM.SelfHost"/>
  </configSections>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>
  <AssembliesLoad>
    <add assemblyName="CM.API.dll" />
  </AssembliesLoad>
</configuration>

至此,web api的承载方式就已经阐述完毕,说一下个人倾向,通过两篇文章对承载的了解,我喜欢使用OwinselfHost承载,并采用自定义配置文件的方式加载外部api程序集,Owin有跨平台功能,但没有去进行验证,大家有兴趣可以去验证下

Web API 之SelfHost与OwinSelfHots加载外部程序的更多相关文章

  1. Request Entity Too Large for Self Hosted ASP.Net Web API在Selfhost的api后台怎么解决Request Entity Too Large问题

    Request Entity Too Large for Self Hosted ASP.Net Web API在Selfhost的api后台怎么解决Request Entity Too Large问 ...

  2. web.xml中配置启动时加载的servlet,load-on-starup

    web.xml中配置启动时加载的servlet,load-on-starup 使用servlet来初始化配置文件数据: 在servlet的配置当中,<load-on-startup>1&l ...

  3. java web.xml listener servlet 和filter加载顺序

    在该项目中总会遇到一些关于加载的优先问题.最近遇到了同样的类别似的,所以,如果你发现信息汇总下,以下是转载其他一些人,毕竟,人们写的不错.它不重复创建的轮.只是略作修改自己的观点. 首先能够肯定的是, ...

  4. AMD和RequireJS初识----优化Web应用前端(按需动态加载JS)

    RequireJS是一个非常小巧的JavaScript模块载入框架,是AMD规范最好的实现者之一.最新版本的RequireJS压缩后只有14K,堪称非常轻量.它还同时可以和其他的框架协同工作,使用Re ...

  5. Android浏览本地 API文档 + 解决页面加载慢的问题

    火狐浏览器安装离线浏览插件: 用浏览器打开index.html文件,你会发现加载的很慢,原因你懂的,为此,我们可以通过离线的方式 查看本地API文档,用火狐浏览器  +   Work Offline插 ...

  6. 移动端web页面列表类上拉加载,查看详情,iframe嵌套第三方页面遇到的问题以及解决办法

    1.移动端上拉加载 网上有很多成熟的插件,比如iscroll.在这里介绍一下用jquery和js写的上拉加载方法.使用原生的去写上拉加载更多需要三个高度去做对比,以新闻类列表举例,首先需要整个dom的 ...

  7. Java之——Web项目中DLL文件动态加载方法

    本文转自:https://blog.csdn.net/l1028386804/article/details/53903557 在Java Web项目中,我们经常会用到通过JNI调用dll动态库文件来 ...

  8. arcgis api for javascript本地部署加载地图

    最近开始学习arcgis api for javascript,发现一头雾水,决定记录下自己的学习过程. 一.下载arcgis api for js 4.2的library和jdk,具体安装包可以去官 ...

  9. web.xml中监听器如何顺序加载

    最近用到在Tomcat服务器启动时自动加载数据到缓存,这就需要创建一个自定义的缓存监听器并实现ServletContextListener接口, 并且在此自定义监听器中需要用到Spring的依赖注入功 ...

随机推荐

  1. 求助,如何干掉这个不要脸的“流氓”

      问题 chrome 第一次打开时,被一个加"7654 导航"的网站捆绑. 查看设置中启动页中,被设置如下:   解决   域名查看,阿里竟然为这样的网站搞隐私保护   尝试 安 ...

  2. Jmeter接口压力测试

    SOAP百科:Soap简单对象访问协议,是交换数据的一种协议规范,是一种轻量的.简单的.基于XML(标准通用标记语言下的一个子集)的协议,它被设计成在WEB上交换结构化的和固化的信息.webServi ...

  3. 使用Topshelf组件构建简单的Windows服务

    很多时候都在讨论是否需要了解一个组件或者一个语言的底层原理这个问题,其实我个人觉得,对于这个问题,每个人都有自己的看法,个人情况不同,选择的方式也就会不同了.我个人觉得无论学习什么,都应该尝试着去了解 ...

  4. 利用shell批量改名和linux中取随机数的方法

    先批量创建文件 #!/bin/sh if [ ! -d /tmp/chenyao ] then mkdir /tmp/chenyao -p fi cd /tmp/chenyao ..} do touc ...

  5. Spring MVC 处理异常的3种方式

    使用Spring MVC开发的博客网站时,遇到了如何处理业务层抛出的异常的问题,查阅到了spring官方博客-spring MVC中异常的处理,以下将会以登录模块为示例. 愚蠢的处理方式 处理异常遵循 ...

  6. 基于ThinkPHP 5.0与Vue.JS 2.x的前后端开源开发框架VueThink

    VueThink 项目介绍 VueThink是一套基于Vue全家桶(Vue2.x + Vue-router2.x + Vuex)+ Thinkphp的前后端分离框架. 脚手架构建也可以通过vue官方的 ...

  7. httpclient源码分析之MainClientExec

    MainClientExec是HTTP请求处理链中最后一个请求执行环节,负责与另一终端的请求/响应交互,也是很重要的类. 源码版本是4.5.2,主要看execute方法,并在里面添加注释.接着详细说下 ...

  8. MAC下Xcode配置opencv(2017.3.29最新实践,亲测可行)

    本文原创,未经同意,谢绝转载!(转载请告知本人并且经过本人同意--By Pacific-hong) 本人小硕一枚,因为专业方向图像相关,所以用到opencv,然后网上MAC下Xcode配置opencv ...

  9. Struts2的类型转换(上)

    传统的类型转换.(略) Struts2中提供了内置的基本的类型转换器,可以实现基本类型的自动转换,包括: Integer, Float, Double, Decimal Date and Dateti ...

  10. 推荐virtualBox虚拟机及安装使用的注意事项

    推荐选择virtualBox虚拟机 选择vbox是因为,本人觉得使用起来比VMware要方便. 简要说明: 本人自学前端开发,对于linux了解很少,直接上手真实的linux环境会很不适应,所以选择了 ...