ASP.NET WebAPI框架解析第二篇(HttpModule的创建和使用)
我们先看一下执行流程图
图中画红圈的部分便是HttpModule,在说创建HttpModule之前,先说一下HttpApplication对象,HttpApplication对象由Asp.net框架创建,每个请求对应一个HttpApplcation实例对象,Asp.Net框架内部维护了一个HttpApplication对象池,可以复用该对象,以便节省服务器资源。HttpApplication对象内部有许多事件,其中的一些事件如下:
BeginRequest Asp.net处理的第一个事件,表示处理的开始
AuthenticateRequest 验证请求,一般用来取得请求用户的信息
PostResolveRequestCache 已经完成缓存的获取操作
……
EndRequest 本次请求处理完成
其中PostResolveRequestCache 这个事件就被路由模块监听了。我们看看一个标准HttpModule模块的接口定义是怎么样的。
public interface IHttpModule
{
void Init(HttpApplication context);void Dispose();
}
注意到Init(HttpApplication context)这个方法,每注册一个HttpModule模块,Asp.Net框架内部通过反射获取对应的程序集,并通过反射调用Init方法,Context参数便是处理一个Http请求的HttpApplication实例对象。那怎么让我们注册的模块参与到处理Http请求中呢?前面提到HttpApplication内部有许多事件,而我们的HttpModule中的Init方法会被Asp.Net框架调用,所以我们可以利用这个去注册相应的事件,执行我们的代码,我们在这里可以做很多事,比如自定义验证、自定义授权,图片压缩,图片加水印,服务器日志记录、恶意请求拦截等等。
为了演示自定义HttpModule的使用,我们创建一个寄宿模式为WebHost的WebAPI,为了便于理解ASP.NET WebAPI的组成,我们不直接创建一个WebAPI模板的项目。
1.使用VS2017创建一个空的解决方案
2.新建一个空的.NetFramwork类库项目和一个空的ASP.NET Web应用
我们对WebAPI类库项目引用WebAPI所需的System.Web.Http.dll。我在I:\Program Files (x86)\Microsoft Visual Studio\Shared\Packages\Microsoft.AspNet.WebApi.Core.5.2.7\lib\net45路径下找到了该dll。
然后在WebAPI项目下建立一个类,使用命名空间System.Web.Htpp,继承该命名空间下的ApiController即可,然后定义一个方法,我定义的如下。注意类名一定要以Controller结尾,否则在路由匹配成功后,WebAPI框架内部不能通过路由解析到的值去反射构建对应的控制器实例对象。
然后对WebHost项目引用如下dll(我都是在I:\Program Files (x86)\Microsoft Visual Studio\Shared\Packages\目录下找到的,实在找不到就创建一个WEBAPI模板然后到项目目录下的Package文件中去拷贝)
System.Web.Http.dll
System.Web.Http.WebHost.dll
System.Net.Http.Formatting.dll
WebHost项目还要保持对WebAPI项目的引用。
为WebHost项目添加Global.asax文件,VS为我们自动创建了一个Global类,并继承于System.Web命名空间下的HttpApplication类。这个类就是处理Http请求的类。我们也可以在这里监听相应的事件,监听函数格式以XXX_XXX的形式定义,至于为什么要这么定义的原因是为了便于通过反射进行注册。有些事件只能在这里监听,比如Application_Start,Application_Start在整个应用生命周期中只会执行一次,相当于静态构造函数.我们在Application_Start中去注册全局的路由表,在WebHost模式下,WebAPI的路由系统实际上由ASP.NET的路由系统完成的,当然WebAPI本身的路由系统也可以完成。我们注册以下路由表。
protected void Application_Start(object sender, EventArgs e)
{
GlobalConfiguration.Configuration.Routes.MapHttpRoute(name: "first",routeTemplate: "webapi/{controller}/{action}");}
然后在VS2017环境下使用IIS Express启动,然后在浏览器输入http://localhost:63210/webapi/home/index,注意在我这里端口号是63210。便可得到如下结果。
我们回顾一下这个流程。
->客户端(在这里是浏览器)发起HTTP请求
->IIS Express接收到该请求
->IIS Express发现该请求路径不是已知的静态资源类型,进而把请求交给Asp.Net托管代码处理
->Asp.Net从HttpApplication池中取一个实例对象去处理该Http请求
->注册相应HttpModule模块,并调用Init()函数,这个时候HttpContext还没有形成,我们只能在这里注册相应的监听事件函数。
->HttpContext形成,HttpApplication实例对象内部的事件轮流触发,其中有一个PostMapRequestHandler事件,在这个事件触发后,会调用相应HttpHandler执行相应的处理,后面再说HttpHandler
->必要的事件触发完成之后生成Http报文并交由IIS Express返回给客户端
->客户端接受Http报文并解析显示在客户端中。
这只是一个大概的过程,具体比这复杂,但我们关注点在HttpModule上,所以足够了。
我们现在尝试自己创建HttpModule
我在WebHost项目下建立了一个文件夹,然后新建了一个AuthorizeHttpModule,模拟授权,功能很简单,看Http请求头中是否包含name字段,并且值为HK,否则,向Http响应报文中的Body部分写入内容,并拦截请求。
namespace WebHost.HttpModules
{
public class AuthorizeHttpModule : IHttpModule
{
public void Dispose()
{
return;
}public void Init(HttpApplication context)
{
//此时HttpContext还未构建完成,不能在这里操作HttpContext
//注册事件监听函数
context.BeginRequest += Authorize;
}
private void Authorize(object sender,EventArgs e)
{
HttpApplication app = sender as HttpApplication;if (app.Request.Headers.Get("name") != "HK")
{
//不加这一行客户端可能不能自动正确的解析字符编码
app.Response.Headers.Add("content-Type", "text/html;charset=utf-8");
//通过Write(string s)写入的字符串在内部默认被转换为utf-8编码。C#string默认编码为UTF-16
//要先写入原始的字符串编码,调用BinaryWrite(byte[] bytes)
app.Response.Write("验证不通过!");
app.CompleteRequest();
}
}
}
}
在WebHost项目目录下的Web.Config中配置HttpModule信息,以便Asp.Net框架读取。注意,有个全局的Web.Config文件,其中默认注册了许多HttpModule,其中有一个HttpModule(WebDAVModule)会截断Put和Delete请求。
如上,我添加了system.webServer节点(IIS集成模式下是这样配置,经典模式自行搜索),并在子节点modules下添加了自定义的HttpModule,其中name是HttpModule名称,ASP.NET内部会以这个名称作为Key,type表示HttpModule的类型名,以便反射读取相应的类型对象。该类型所在的程序集必须在Web应用程序的Bin目录,否则不能正常加载,由于我创建的HttpMudle是在WebHost项目中,所以不会出现问题。我们现在启动IIS Express看看效果。
可以看到我们的HttpModule起作用了。我们用PostMan为请求头添加一个字段name,值为HK,然后请求/webapi/home/index试试看
可以看到没有被拦截。前面我们提到了一个HttpHandler,这个HttpHandler实际上是最终处理页面的处理者,后面再说。
ASP.NET WebAPI框架解析第二篇(HttpModule的创建和使用)的更多相关文章
- ASP.NET WebAPI框架解析第一篇
ASP.NET WebAPI有两种寄宿模式,一种是WebHost,一种是SelfHost,为什么可以有两种模式的原因在于WebAPI有一个相对独立的消息处理管道,只要给这个消息管道传递一个封装好的对象 ...
- ASP.NET MVC案例教程(基于ASP.NET MVC beta)——第二篇:第一个页面
摘要 本文首先一步一步完成Demo的第一个页面——首页.然后根据实现过程,说明一下其中用到的与ASP.NET MVC相关的概念与原理. 让第一个页面跑起来 现在,我们来实现公告系统 ...
- ASP.NET Core 学习笔记 第二篇 依赖注入
前言 ASP.NET Core 应用在启动过程中会依赖各种组件提供服务,而这些组件会以接口的形式标准化,这些组件这就是我们所说的服务,ASP.NET Core框架建立在一个底层的依赖注入框架之上,它使 ...
- ASP.NET WebApi 学习与实践系列(1)---如何创建 WebApi
写在前面 最近在做一个app的时候发现需要写后台服务.所以,在考虑是使用webapi还是使用webserver来写这个后台服务的时候.爱纠结的我,最后还是选择了使用webapi来写这个后台服务. 原因 ...
- Lucene&Solr框架之第二篇
2.1.开发环境准备 2.1.1.数据库jar包 我们这里可以尝试着从数据库中采集数据,因此需要连接数据库,我们一直用MySQL,所以这里需要MySQL的jar包 2.1.2.MyBatis的jar包 ...
- SpringMVC框架之第二篇
6.参数绑定(重点) Springmvc作为表现层框架,是连接页面和service层的桥梁,它负责所有请求的中转.怎么从请求中接收参数是重点,这也体现了我们刚开始说的Springmvc的第一个作用:“ ...
- Django框架之第二篇--app注册、静态文件配置、form表单提交、pycharm连接数据库、django使用mysql数据库、表字段的增删改查、表数据的增删改查
本节知识点大致为:静态文件配置.form表单提交数据后端如何获取.request方法.pycharm连接数据库,django使用mysql数据库.表字段的增删改查.表数据的增删改查 一.创建app,创 ...
- Django(三)框架之第二篇
https://www.cnblogs.com/haiyan123/p/7717788.html 一.知识点回顾 1.MTV模型 model:模型,和数据库相关的 template:模板,存放html ...
- Django框架之第二篇
一.知识点回顾 1.MTV模型 model:模型,和数据库相关的 template:模板,存放html文件,模板语法(目的是将变量如何巧妙的嵌入到HTML页面中). views:视图函数 另加urls ...
随机推荐
- 关于 conda中的 lxml 无法导入 etree 问题
找到你conda的安装目录下\Lib\site-packages下的两个文件夹lxml和lxml-4.3.4.dist-info,将这两个文件夹删除. 执行命令pip install lxml 重新安 ...
- 前端基础进阶(十四):es6常用基础合集
在实际开发中,ES6已经非常普及了.掌握ES6的知识变成了一种必须.尽管我们在使用时仍然需要经过babel编译. ES6彻底改变了前端的编码风格,可以说对于前端的影响非常巨大.值得高兴的是,如果你熟悉 ...
- Win10企业版远程桌面结合frp实现公网远程
Win10企业版远程桌面结合frp实现公网远程 前言 由于经常下班后还要处理问题,但是又没有运维那么频繁,就不想天天背着电脑来回跑,刚开始用的teamviewer,后来被商业劝退了(就是不让用了,让买 ...
- 【PyTorch】深度学习与PyTorch资料链接整理
欢迎来到我的博客! 以下链接均是日常学习,偶然得之,并加以收集整理,感兴趣的朋友可以多多访问和学习.如果以下内容对你有所帮助,不妨转载和分享.(Update on 5,November,2019) 1 ...
- [Office#PPT]0001.实例剖析-如何制作一个牛B的融资PPT
一些好公司明明在模式上富有创新性,但却在 pitch 时很保守,而且他们又不缺设计和开发能力.如何设计你的融资演讲稿才会吸引投资人对你投资?投资人 Daniel Eckler给大家贡献了下面这篇技术贴 ...
- css 3 背景图片为渐变色(渐变色背景图片) 学习笔记
6年不研究CSS发现很多现功能都没有用过,例如渐变色,弹性盒子等,年前做过一个简单的管理系统,由于本人美工不好,设计不出好看的背景图片,偶然百度到背景图片可以使用渐变色(感觉发现了新大陆).以后的项目 ...
- 《学习scrapy框架爬小说》的进一步完善
一.完善目标: 1.为方便使用,把小说拼音或英文名,小说输出中文名,第一章节url地址变量化,修改这些参数即可爬取不同的小说. 2.修改settings.py设置文件,配置为记录debug的log信息 ...
- kubeadm实现k8s高可用集群环境部署与配置
高可用架构 k8s集群的高可用实际是k8s各核心组件的高可用,这里使用主备模式,架构如下: 主备模式高可用架构说明: 核心组件 高可用模式 高可用实现方式 apiserver 主备 keepalive ...
- A barrier for Mobile Forensics - Samsung Secure Folder
Since I mentioned about "Second Space", let's take a look at Samsung "Secure Folder&q ...
- 使用Mac的Remote Desktop Manager连接ubuntu16.04 & Win10的远程桌面
疫情严重,公司实行远程办公.自己只有mac电脑,苦于3个系统间跨平台建立远程桌面. 今天,终于尝试成功!特来记录,以防别人踩坑! Mac远程软件安装 Remote Desktop Manager软件非 ...