URL重写与URL路由
要介绍这两个内容,必须要从ASP.NET管线说起。
ASP.NET管线
管线(Pipeline)这个词形象地说明了每个Asp.net请求的处理过程: 请求是在一个管道中,要经过一系列的过程点,这些过程点连接起来也就形成一条线。 这些一系列的过程点,其实就是由HttpApplication引发的一系列事件,通常可以由HttpModule来订阅, 也可以在Global.asax中订阅,这一系列的事件也就构成了一次请求的生命周期。
下面通过两张图片来详细说明一下请求的过程
第一张图,主要展示:请求的过程

从上面的图中,我们可以看出
1.请求先交给HttpModule处理,然后由HttpModule交给HttpHandler,最后再由HttpHandler交回给HttpModule,由HttpModule结束请求。
2.Session的有效期,只有在HttpHandler处理时有效。HttpModule处理时,都是无效的。
3.整个过程由一系列的事件组成,这点正应验了前面对管线的定义。
第二张图,主要说明:管线中所有事件的意义

注意:这是iis7的处理过程,其中多了LogRequest与PostLogRequest这两个事件。iis6的处理过程并没有这两个事件。
对于各个事件的含义,我想图片已经解释的很清楚了。
下面通过一个案例,来讲解一下本篇博客的主题。
案例需求:第三方以这样的url:http://host:port/xxxx/mobile/form?Id=xxxxx。向系统发出请求时。系统可以将该url映射到对应的业务层。由于本次主要讲解的重点不在业务层,所以就将该url直接映射到一个简单业务层,输入Hello+Query
URL重写
中心思想:将请求的url重写成服务器可以处理的url形式。然后由服务器根据重写后的url,查找出可以处理重写后的url的Handler,最后由Handler对其进行处理。
思路:
1.定义url重写后的样子。比如将url:http://host:port/xxxx/mobile/form?Id=xxxxx。重写成:http://host:port/xxxx/mobile/service.mobile?Id=xxxxx。
2.编写自定义Module:IHttpModule,检测url是否是需要重写的url,如果是重写url。由管线根据重写后的url来寻找对应的Handler对其进行处理。
3.编写自定义Handler:IHttpHandler,来处理重写后的url。
步骤:
1.编写自定义Module
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web; namespace Service
{
/// <summary>
/// url重写Module
/// </summary>
internal class UrlRewriteModule : IHttpModule
{
/*
* 为了演示简单,直接写死地址
* 这里我写了两个url,一个从虚拟路径的根路径重写(我本机的虚拟路径是/Web);另一个从url的末尾处重写
* 具体用哪个url,根据需求。但是有一点要注意,如果采用根路径重写方式,
* 那么服务器上的虚拟路径、重写后的url的虚拟路径、Web.config中<httpHandlers>节点下配置的path的虚拟路径都必须相同,
* 否则Module无法根据url映射对应的Handler
*/
public static string rootUrlPattern = "/Web/service.mobile";
//public static string urlPattern = "service.mobile"; public void Init(HttpApplication app)
{
app.PostAuthorizeRequest += app_PostAuthorizeRequest;
} void app_PostAuthorizeRequest(object sender, EventArgs e)
{
HttpApplication app = sender as HttpApplication; //检测是否是要重写的url(这里最好用正则表达式匹配)
if (app.Context.Request.Url.PathAndQuery.Contains("mobile/form"))
{
//检查url中是否带有参数
int p = app.Request.Path.IndexOf("?");
if (p > )
{
//重写url,并且将url参数进行拼接
app.Context.RewritePath(rootUrlPattern
+ "&" + app.Request.Path.Substring(p + ));
}
else
{
//重写url(url中不带参数)
app.Context.RewritePath(rootUrlPattern);
}
} } public void Dispose()
{
}
}
}
2.编写自定义Handler
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web; namespace Service
{
public class UrlHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
HttpRequest request = context.Request;
string result = string.Empty;
if (!string.IsNullOrEmpty(request.Form["ID"]))
{
string id = request.Form["ID"];
result = "Hello " + id;
}
else
{
result = "Hello";
}
context.Response.Write(result);
} public bool IsReusable
{
get
{
return false;
}
}
}
}
3.Web.config配置
<httpHandlers>
<add path="/Web/service.mobile" verb="*" validate="false" type="Service.UrlHandler,Service"/>
</httpHandlers>
<httpModules>
<add name="UrlRewriteModule" type="Service.UrlRewriteModule,Service"/>
</httpModules>
4.测试页面
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<script src="Scripts/jquery-1.8.2.js" type="text/javascript"></script>
<script type="text/javascript">
function formTest() {
$.ajax({
type: "POST",
url: "mobile/form",
data: { ID: "wolf" },
complete: function (XHR, TS) {
XHR = null;
},
success: function (msg) {
alert(msg);
}
});
}
</script>
</head>
<body>
<input type="button" value="发起请求" onclick="formTest();" />
</body>
</html>
以上代码有2点需要说明
1.选择注册PostAuthorizeRequest(用户已经得到授权)事件中重写url。因为
a.用户验证,用户授权都让其按照asp.net框架自行运行。
b.PostAuthorizeRequest的下一个事件是ResolveRequestCache(获取以前处理缓存的处理结果)。如果本次请求的url在之前处理过,那么会直接点用缓存结果,而不会再进行处理工作。如果我写在ResolveRequestCache事件之后,如果缓存中有处理结果。那么后面的事件都有可能被跳过(EndRequest不会被跳过)。所以我选择在PostAuthorizeRequest事件中重写url。
2.自定义Module中,有关于url重写时需要注意虚拟路径的一段描述。
如果采用根路径重写方式,那么服务器上的虚拟路径、重写后的url的虚拟路径、Web.config中<httpHandlers>节点下配置的path的虚拟路径都必须相同,否则Module无法根据url映射对应的Handler。
URL路由
中心思想:检测url是否是需要处理的格式。然后直接指定Handler对重写后的url进行处理(这点就是url路由与url重写的区别,url路由是指定Handler来对重写后的url进行处理,而url重写是交给管线,让其寻找能处理重写后的url的Handler)
思路:
1.编写自定义Module:IHttpModule,检测url是否是需要处理的格式,如果是由管线根据重写后的url来寻找对应的Handler对其进行处理。
2.编写自定义Handler:IHttpHandler,来处理重写后的url。
步骤
1.编写自定义Module
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web; namespace Service
{
/// <summary>
/// URL路由
/// </summary>
internal class UrlRoutingModule : IHttpModule
{
public void Init(HttpApplication app)
{
app.PostResolveRequestCache += app_PostResolveRequestCache;
} void app_PostResolveRequestCache(object sender, EventArgs e)
{
HttpApplication app = sender as HttpApplication; //检测是否是要重写的url(这里最好用正则表达式匹配)
if (app.Context.Request.Url.PathAndQuery.Contains("mobile/form"))
{
app.Context.RemapHandler(new UrlHandler());
}
} public void Dispose()
{
}
}
}
2.编写自定义Handler
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web; namespace Service
{
internal class UrlHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
HttpRequest request = context.Request;
string result = string.Empty;
if (!string.IsNullOrEmpty(request.Form["ID"]))
{
string id = request.Form["ID"];
result = "Hello " + id;
}
else
{
result = "Hello";
}
context.Response.Write(result);
} public bool IsReusable
{
get
{
return false;
}
}
}
}
3.Web.config配置(只需要配置httpModules节点)
<httpModules>
<add name="UrlRoutingModule" type="Service.UrlRoutingModule,Service"/>
</httpModules>
4.测试页面
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<script src="Scripts/jquery-1.8.2.js" type="text/javascript"></script>
<script type="text/javascript">
function formTest() {
$.ajax({
type: "POST",
url: "mobile/form",
data: { ID: "wolf" },
complete: function (XHR, TS) {
XHR = null;
},
success: function (msg) {
alert(msg);
}
});
}
</script>
</head>
<body>
<input type="button" value="发起请求" onclick="formTest();" />
</body>
</html>
以上代码有2点需要说明
1.PostMapRequestHandler(根据用户请求,创建处理请求对象)事件是asp.net框架根据请求选择Handler的事件。所以,如果想自定义选择Handler,一定要选择管线中在其事件之前的事件。而比较早的事件,例如:验证用户事件、授权事件,都让asp.net框架帮我们处理。
2.本次在Web.config配置中,只要配置httpModule节点就可以。因为url路由是自定义选择Handler,并不需要asp.net框架根据请求选择对应的Handler,所以Handler节点不需要任何配置。
感谢大家的耐心阅读。
URL重写与URL路由的更多相关文章
- thinkphp URL规则、URL伪静态、URL路由、URL重写、URL生成(十五)
		原文:thinkphp URL规则.URL伪静态.URL路由.URL重写.URL生成(十五) 本章节:详细介绍thinkphp URL规则.URL伪静态.URL路由.URL重写.URL生成 一.URL ... 
- IIS8如何安装和使用URL重写工具-URL Rewrite
		下载和安装URL Rewrite IIS8默认是没有安装URL重写工具的,必须要自己下载安装. 如果IIS上默认有安装Web平台安装程序,我们可以使用平台自动安装URL Rewrite重写工具,打开I ... 
- URL重写IIS7(URL Rewrite Module) 比之前的urlrewrite更方便使用
		原文发布时间为:2011-02-24 -- 来源于本人的百度文章 [由搬家工具导入] 微软在IIS7中添加了URL的重写模块,并且免费使用,可以导入.htaccess规则,确实是个不错的选择 URL ... 
- 转载MSDN 在ASP.NET 中执行 URL 重写
		转载文章原网址 http://msdn.microsoft.com/zh-cn/library/ms972974.aspx 摘要:介绍如何使用 Microsoft ASP.NET 执行动态 URL 重 ... 
- IIS进行URL重写
		一.Why? 1.先来讲一讲为什么我们要使用url重写这个东西 2.因为我学习的后端是nodejs,然后我发现nodejs一个非常让人难受的事,就是它监听端口不是80和443时,你访问网页需要输入端口 ... 
- Nginx实现URL重写
		本文利用Nginx实现URL重写,本文使用Nginx与静态页面配合重写URL. 1.准备工作. 结合本文场景,需要安装Nginx. 1.1 关于Linux系统安装Nginx可以参考我的文章---(传送 ... 
- URL重写2.1.mis
		概观 IIS URL重写2.1使Web管理员能够创建强大的规则来实现更容易让用户记住的网址,并使搜索引擎更容易找到.通过使用规则模板,重写映射,.NET提供程序和集成到IIS管理器中的其他功能,Web ... 
- ASP.NET Core 2 学习笔记(八)URL重写
		路由跟URL 重写的功能性略有不同.路由是将Request 找到对应的服务,而URL 重写是为了推卸责任转送Request.本篇将简单介绍下ASP.NET Core的URL重写(URL Rewrite ... 
- Beetlex服务框架之Webapi访问限制和url重写
		在新版本的BeetleX.FastHttpApi中集成了IP访问策略和URL重写两个功能,通过IP访问策略可以制定服务针对不同IP的访问限制控制:而URL重写则可以制定更好的URL访问方式.以下介绍这 ... 
随机推荐
- python的时间差计算
			import time start = time.clock() #当中是你的程序 elapsed = (time.clock() - start) print("Time used:&qu ... 
- Spark-2.0原理分析-shuffle过程
			shuffle概览 shuffle过程概览 shuffle数据流概览 shuffle数据流 shuffle工作流程 在运行job时,spark是一个stage一个stage执行的.先把任务分成stag ... 
- 5分钟带你入门vuex(vue状态管理)
			如果你之前使用过vue.js,你一定知道在vue中各个组件之间传值的痛苦,在vue中我们可以使用vuex来保存我们需要管理的状态值,值一旦被修改,所有引用该值的地方就会自动更新,那么接下来我们就来学习 ... 
- linux 常用清理或备份文件命令
			find /data/tmp/confluence/backups/ -type f -mtime +7 -exec rm -f {} \; ##查找创建超过7天的文件并强制删除 cp /data/a ... 
- java和python中的string和int数据类型的转换
			未经允许,禁止转载!!! 在平时写代码的时候经常会用到string和int数据类型的转换 由于java和python在string和int数据类型转换的时候是不一样的 下面总结了java和python ... 
- iOS 开发笔记-UILable/UIFont/UIButton常见设置
			UILabel的常见设置 @property(nonatomic,copy) NSString *text; 显示的文字 @property(nonatomic,retain) UIFont *fon ... 
- SSH无密码登录:只需两个简单步骤 (Linux)
			最后更新 2017年4月8日 分类 最新文章 服务器安全 标签 RSA SSH Key 非对称加密 如果你管理一台Linux服务器,那么你就会知道每次SSH登录时或者使用scp复制文件时都要输入密码是 ... 
- Linux基础命令---dumpe2fs
			dumpe2fs 显示ext2.ext3.ext4文件系统的超级快和块组信息.此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.SUSE.openSUSE.Fedora. 1.语法 ... 
- python之路----进程三
			IPC--PIPE管道 #创建管道的类: Pipe([duplex]):在进程之间创建一条管道,并返回元组(conn1,conn2),其中conn1,conn2表示管道两端的连接对象,强调一点:必须在 ... 
- MP4v2 基本使用(二)
			MP4转H264文件 本文最目标是基本的MP4v2接口的使用,并且实现一个简单的提取mp4文件里面264流的功能: 1.264文件基本知识 下看看H264文件的基本常识 NAL 头 0x00 0x00 ... 
