您的位置:首页 > 其它

使用UrlRewriter进行Url重写的完整解决方案

2008-11-06 13:24 441 查看

Setp 1:

下载UrlRewriter => http://urlrewriter.net[/b]/

Setp 2:

将其添加到Web项目的Bin目录下

Setp 3:

配置:打开web.config,在configSecions中添加sectionHandler:
<section name="rewriter[/b]" requirePermission="false" type="Intelligencia.UrlRewriter.Configuration.
RewriterConfigurationSectionHandler, Intelligencia.UrlRewriter" />添加这个section是为了它能够处理web.config中的节;然后对UrlRewriter配置url[/b]重写规则:
<rewriter[/b]>
<rewrite url[/b]=”~/lmh$” to=”~/Users.aspx?user=lmh” processing=”stop” />
</rewriter[/b]>url[/b]是可以使用正则表达式的。比如上面的例子,就是将http://www.***.net[/b]/lmh重写到http://www.***.net[/b]/Users.aspx?user=lmh,$在正则表达式中表示是串的结束,也就是说http://www.***.net[/b]/lmhe是不会被重写到to后的地址的,如果把$去掉则可以。

Setp 4:

使rewriter[/b]生效:UrlRewriter是在HttpModule中做url[/b]重写的,要使重写生效,就得先把HttpModule添加到web.config中:
<httpModules>
<add name="UrlRewriter" type="Intelligencia.UrlRewriter.RewriterHttpModule, Intelligencia.UrlRewriter"/>
</httpModules>

Setp 5:

让ReWriter[/b]有机会重写Url[/b]: 当iis收到一个请求时,并不是都会扔给asp.net[/b](aspnet_isapi.dll)来处理,比如静态html,默认情况下,当请求html页面时,iis直接就把结果抛给了客户端,之所以.aspx页面会被asp.net[/b]引擎处理,是因为在iis有进行处理程序映射,.aspx被映射到aspnet_isapi.dll,所以当iis收到请求时,先看后缀名,如果是aspx,那就把它交给aspnet_isapi.dll来处理。因为UrlRewriter是asp.net[/b]级别的重写组件,所以,假如要想执行setp3中例子那样的重写,得先让UrlRewriter有机会收到这个地址的请求才行(默认UrlRewriter是没机会处理这个url[/b]的,因为iis收到这个地址的请求时,因为它没有映射到aspnet_isapi.dll,所以会直接抛出404找不到的错误,因此,要替它做这个映射。打开iis,在属性中有这一项,我们可以让*映射到aspnet_isapi.dll,这样所有的文件都交给asp.net[/b]来处理了,UrlRewriter也就有机会出手了。
如果用的是IIS7.0,则不用这么麻烦,整个Setp4可以简化为:在web.config中的节的节中添加上UrlRewriter:
<add name="UrlRewriter" type="Intelligencia.UrlRewriter.RewriterHttpModule, Intelligencia.UrlRewriter"/>这会保证所有的请求都会经过asp.net[/b]的这个Module。
现在,重写就算基本完成了,但有几个问题:

Problem 1:

图片可能不显示:如果进行Url[/b]
Rewirte并且页面中的图片引用是使用相对路径的话,很可能会发现图片无效了,这是因为,假如/Users/lmh会被重写为
/Users.aspx?user=lmh,而Users.aspx上有一张图片,放在相同目录下:logo.gif,(Users.aspx中是<img src="http://www.shenjk.com/logo.gif" />)那当请求/Users/lmh时,浏览器对logo.gif的请求的路径将变成/Users/logo.gif,而实际上logo.gif是要用/logo.gif才能请求得到的,所以,为了保证Url[/b] rewrite后不会出现这个问题,需要使用<img src="http://www.shenjk.com//logo.gif" />,但是当使用UrlRewriter时,对于Css,如果代码中是,而实际用Users/lmh去请求的话,会发现其实已经变成了,而图片,如果是用的服务器控件的话,也可以继续使用相对路径,就不存在标题中的问题。

Problem 2:

Asp.net[/b]的postback会导致真实地址又被嚗光:还是setp3的例子,假设Users.aspx中有一个服务器按钮控件,当第一次请求时,确实OK,但是一旦点击了那个按钮,地址栏又变成了http://www.***.net[/b]/Users.aspx?user=lmh,原因是asp.net[/b]的服务器form控件的action默认都是指定当前页面地址的,虽然我们收到的请求是…/lmh,但经过UrlRewrite后,asp.net[/b]处
理的已经是真实的地址:…/Users.aspx?user=lmh,所以在form被Render时,action会是..
/Users.aspx?user=lmh,那么,要解决这个问题,就是让form的action的值也被render为请求的地址,这个网上已经有答案
了,就是利用ControlAdapter(写在App_Code中即可,不过为了重用,可以放到类库项目中):




FormRewriterControlAdapter
1

public class FormRewriterControlAdapter : System.Web.UI.Adapters.ControlAdapter
2





{
3

protected override void Render(HtmlTextWriter writer)
4





{
5

base.Render(new RewriteFormHtmlTextWriter(writer));
6

}
7

}
8


9

public class RewriteFormHtmlTextWriter : HtmlTextWriter
10





{
11

public RewriteFormHtmlTextWriter(HtmlTextWriter writer)
12

: base(writer)
13





{
14

this.InnerWriter = writer.InnerWriter;
15

}
16


17

public override void WriteAttribute(string name, string value, bool fEncode)
18





{
19

if (name == "action")
20





{
21

HttpContext context = HttpContext.Current;
22


23

value = context.Request.RawUrl;
24

}
25

base.WriteAttribute(name, value, fEncode);
26

}
27

}这段代码是来自Jeffery Zhao的博客文章(我去掉了其中一些代码,只保留了保证会工作的最基本代码)。
需要说明的一点是:HtmlTextWriter有两个WriteAttribute方法:
public virtual void WriteAttribute(string name, string value, bool fEncode)public virtual void WriteAttribute(string name, string value) 重写下面的那个WriteAttribute是不能成功的,必须重写上面那个方法。为什么呢?先调试看看。
会发现如果重写的是上面那个方法,则会有一次传进来的name值是"action",如我所愿,而重写下面那个方法则没发现传进来值是”action”的name参数。这是怎么搞的?
首先我们要知道,下面那个方法其实是简单的调用了上面的WriteAttribute :
public virtual void WriteAttribute(string name, string value) { WriteAttribute(name, value, false /*encode*/);}这
是framework中的源码。那么,我们所可以猜测到的,就是action这个属性不是通过调用WriteAttribute(“action”,
“…”)来渲染的,而是直接调用WrtiteAttribute(“action”, “…”,
…),那我们就打开HtmlForm的源代码看看吧(没有源代码的可以用Reflector看),找到
HtmlForm.RenderAttributes(HtmlTextWrtier writer)方法,其中有几行:
writer.WriteAttribute("method", Method);Attributes.Remove("method"); // Encode the action attribute - ASURT 66784 writer.WriteAttribute("action", GetActionAttribute(), true /*encode*/); Attributes.Remove("action");
我们重点看的是上面加粗并下划线的那两行,可以很清楚的看到,当渲染”method”属性时,只是调用了
public virtual void WriteAttribute(string name, string value)
而渲染action属性则是调用了
public virtual void WriteAttribute(string name, string value, bool fEncode)
那么,答案也就浮出水面了。
接下来,我们要让这个Adapter起作用(上面之所以可以调试,是因为我已经让其起作用了,只是还没写出来)。添加Asp.net[/b] Folder:App_Browses,新建一个browser文件:

<browsers> <browser refID="Default"> <controlAdapters> <adapter controlType="System.Web.UI.HtmlControls.HtmlForm" adapterType="FormRewriterControlAdapter"/> </controlAdapters> </browser></browsers>
因为上面的FormRewriterControlAdapter是写在App_Code中的,所以不需要添加命名空间。
这么一来,使用UrlRewriter进行asp.net[/b]级别的UrlRewrite就弄好了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: