ASP.NET Web API: 宿主(Hosting)
ASP.NET Web API 处理架构中介绍了ASP.NET Web API主要有三层组成:宿主(hosting),消息处理管道(message handler pipeline)和控制器处理(controller handling),本篇文章主要介绍宿主(Hosting):包括ASP.NET经典管道上的Web Hosting和WCF堆栈的自宿主SelfHosting。
ASP.NET经典管道上的Web Hosting
1、ASP.NET 路由使您可以使用不必映射到网站中特定文件的 URL。 由于该 URL 不必映射到文件,因此可以使用对用户操作进行描述因而更易于被用户理解的 URL,路由在ASP.NET Web API上一样有重要的位置。在ASP.NET平台上,是通过RouteTable的静态属性Routes添加路由到路由表里,例如下面的代码是ASP.NET MVC项目模板默认定义的路由:
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
大部分的路由逻辑是由UrlRoutingModule附加到ASP.NET 的管道事件PostResolveRequestCache,对每一个Http请求,这个模块在路由集合中匹配符合路由规则,如果有一个匹配,则:
- 从Route Data中获取到一个route handler
- 从Route Handler中获取到一个实现IHttpHandler接口的Http处理程序
- 最后,当前的请求上下文映射到上述Http处理程序
因此,在ASP.NET 管道的最后将请求发送这个处理器。
2、集成Web API,当宿主与ASP.NET,Web API的配置定义在单件的HttpConfiguration对象里,通过静态属性GlobalConfiguration.Configuration访问。Web API还定义了几个RouteCollection 扩展方法,叫做 MapHttpRoute,用来定义Web APi的配置。请看下面的示例:
HttpConfiguration config = GlobalConfiguration.Configuration; config.Routes.MapHttpRoute("default", "{controller}/{id}", new {id = UrlParameter.Optional}); // other configuration settings
上述代码主要完成2项功能:
- 静态属性GlobalConfiguration.Configuration 用于获取配置,指向全局的RouteTable.Routes 路由集合。
- 使用MapHttpRoute扩展方法添加路由配置。
通过MapHttpRoute扩展方法添加到路由集合的Route Handler是HttpControllerRouteHandler,匹配使用MapHttpRoute添加的请求,相关的Route Handler返回一个新的处理器类型 HttpControllerHandler,它实现了异步IAsyncHttpHandler 接口,这个处理器使用路由数据初始化,包含匹配的信息。
当调用HttpControllerHandler的BeginProcessRequest方法,执行下面的动作:
- 从当前的HttpContext创建一个HttpRequestMessage 实例
- 使用GlobalConfiguration.Configuration的配置创建一个HttpServer,然后把这个新的HttpRequestMessage 实例推入服务器管道。
在HttpServer获取请求之后,它就进入了宿主处理新阶段(Web API的新管道)。下面的图总结了路由处理过程和分发到HttpServer实例(信息处理的管道)。
基于WCF堆栈的自宿主SelfHosting
上面我们介绍完了在ASP.NET上的Web宿主,接下来我们来介绍基于WCF堆栈的自宿主SelfHosting。我们先来看一段使用自宿主的代码:
var config = new HttpSelfHostConfiguration("http://localhost:8080"); config.Routes.MapHttpRoute("default", "{controller}/{id}", new { id = RouteParameter.Optional }); var server = new HttpSelfHostServer(config); server.OpenAsync().Wait(); Console.WriteLine("Server is opened");
HttpSelfHostServer 继承与HttpServer,并使用HttpSelfHostConfiguration 作为配置类,类图结构如下:
在HttpSelfHostServer 内部使用的WCF堆栈从传输媒体获取消息然后把他们推送到上层的消息处理管道。下面部分简要介绍WCF的高层架构,Web API自宿主的特征。
WCF架构
WCF架构主要划分为2层,Channel Stack和Service Model,具体看下图:
较低的通道堆栈层是由一堆通道和行为类似于经典的网络协议栈。通道分为两类:传输渠道和协议的渠道。负责传输通道由接口与传输介质(例如TCP,MSMQ,HTTP)(是的,我知道,HTTP不仅仅是一个传输协议),即由讯息的接收与传递。协议的信息渠道流量过程上下通过叠加。一个典型的使用案例的增加协议通道数字签名在发送方和验证签名的人在接收的一面。传输通道,使用编码器转换字节流和信息输送介质字节实例。
上层的Service Model执行消息和方法调用,所处理的人物如下:
- 把收到的消息转换成参数序列
- 获取到使用的服务实例
- 选择调用的方法
- 选择线程处理调用的方法
然而HttpSelfHostServer不使用Service Model层,相反,他直接消费了从传输通道堆栈获取的消息。传输通道堆栈层使用Binding来组织,如下图所示:
Binding是一个有序的Binding Element的集合,每一个元素描述一个通道或者编码器。第一个Binding Element描述了上层通道,最后一个Binding Element描述了底层的通道,总之这是一个传输通道。
HttpSelfHostServer 和HttpSelfHostConfiguration 类
在内部HttpSelfHostserver.OpenAsync 方法基于HttpSelfHostConfiguration实例属性创建和配置创建一个HttpBinding实例。然后他利用这个Binding异步创建一个WCF传输堆栈,他也创建一个Pump把消息推入这个堆栈,并转换为HttpRequestMessage 实例并把新的请求推入HttpServer,下图是消息的处理流程:
使用自宿主的时候,大多数的WCF HTTP binding 约束和设置都是可用的,在配置的内部创建的HttpBinding实例可以用2种方式创建。第一种是使用HttpSelfHostConfiguration属性,例如MaxBufferSize 和TransferMode,这些被用于内部创建HttpBinding实例,第二种方法是创建一个HttpSelfHostConfiguration的子类,然后重写OnConfigureBinding方法,这个方法中有机会在创建通道堆栈之前修改绑定配置。
ASP.NET WebAPI Hosting Techniques http://www.codeproject.com/Articles/555923/ASP-NET-WebAPI-Hosting-Techniques
- NewInstallUserMapper.class阅读笔记
- TimeUtil类所有方法
- mapreduce项目调优
- zookeeper强制关机无法启动Unable to load database on disk具体解决步骤
- Python爬淘宝——300W淘宝文胸说明了什么
- 文本编码转换工具iconv 附批量转换文件编码命令
- 用23行代码爬取豆瓣音乐top250
- GitHub上超9Kstars的Python爬虫项目——pyspider(国人编写)
- 理解zookeeper选举机制
- zookeeper详解
- Python爬虫进阶(一)使用Selenium进行网页抓取
- R语言的优劣
- 学习SQL【10】-SQL高级处理
- 使用Python操作机器人聊天
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Join()和 List()的 6 种化学反应
- lettuce和hbase中对netty的使用你都了解吗?
- SAS-新规试行下诞生的程序
- AIOHTTP的实战(一)
- JMeter二次开发插件实例
- 「R」Obtain RNAseq Values for a Specific Gene in Xena Database
- 使用JMeter测试TCP协议
- SQL使用(一):如何使用SQL语句去查询第二高的值
- OpenCV加载图片显示对应类型(位深度)方法
- 小程序快速入门教程(登录注册、开发工具、文件及结构介绍)
- 面试题-统计字符出现最大次数
- pytorch中文语言模型bert预训练代码
- React环境搭建
- leetcode - 旋转数组的最小数字
- 笔记101 | 文件的压缩与解压笔记