在ASP.NET 2.0中实现URL重写
URL重写技术在今天已不是什么新鲜的话题了,在Apache服务器提供了名为mod_rewrite的URL重写模块,而在IIS服务器上,也有很多商业的ISAPI 筛选器模块可供使用。然而这对于我们,没有很多的资金或使用的共享服务器,使得以上的方法都不是最佳的解决方案。幸而ASP.NET给我们提供了强大的可扩展性,能让我们自己定义页面的访问规则,很方便实现URL重写。
在ASP.NET中实现URL重写,需要创建HTTP模块(HttpModule)或HTTP处理程序(HttpHandler),通过调用HttpContext的RewritePath方法来近进行URL重写。本篇文章使用的是HTTP模块做的示例。
使用HTTP模块执行URL重写
首先需要定义一个实现了IHttpModule接口的类。IHttpModule接口定义了两个方法需要实现:
- Init(HttpApplication)。此方法在初始化HTTP模块后触发。在此方法中,您将把事件处理程序绑定到相应的HttpApplication事件。
- Dispose()。当请求已完成并已发送回IIS时调用此方法。您应当在此处执行所有最终的清除操作。
[code="c#"]
1: public virtual void Init(HttpApplication app) 2: { 3: // WARNING! This does not work with Windows authentication! 4: // If you are using Windows authentication, change to app.BeginRequest 5: app.AuthorizeRequest += new EventHandler(this.URLRewriter); 6: }[/code]
注意:如果要使用窗体身份验证而不使用Windows身份验证,请将URL重写放在AuthorizeRequest事件处理程序中执行。如果要使用Windows身份验证,请在BeginRequest或AuthenticateRequest事件进行过程中安排URL重写。
在URLRewriter方法里的第7行从配置文件里读取URL重写信息,进行处理,如对正则表达式的处理。如您对如何扩展标准的配置文件还不清楚,请看这篇Blog:扩展.NET 2.0标准配置文件[code="c#"]
1: protected void URLRewriter(object sender, EventArgs e) 2: { 3: HttpApplication app = (HttpApplication) sender; 4: string requestedPath = app.Request.Path; 5: 6: // get the configuration rules 7: UrlsCollection rules = UrlsConfig.GetConfig().Urls; 8: 9: for (int i = 0; i < rules.Count; i++) 10: { 11: // get the pattern to look for, and Resolve the Url (convert ~ into the appropriate directory) 12: string lookFor = "^" + RewriterUtils.ResolveUrl(app.Context.Request.ApplicationPath, rules[i].VirtualUrl) + "$"; 13: 14: Regex re = new Regex(lookFor, RegexOptions.IgnoreCase); 15: if (re.IsMatch(requestedPath)) 16: { 17: string sendToUrl = RewriterUtils.ResolveUrl(app.Context.Request.ApplicationPath, re.Replace(requestedPath, rules[i].DestinationUrl)); 18: RewriterUtils.RewriteUrl(app.Context, sendToUrl); 19: break; 20: } 21: } 22: 23: }[/code]
如果匹配,则调用RewriteUrl方法,将URL分解成路径和查询字符串两部分,以调用HttpContext.RewritePath方法来实现URL的重写。其中对“URL资源的附加路径信息”(如:Http://www.microsoft.com/virdir/page.html/tail 的tail部分)未做处理,直接用String.Empty来表示,如您需要,可以自行扩展一下。
OK,到此为止,一个简单的URL重写程序就初步完成了,但还没有大功告成,还有一个细节的问题需要我们处理一下,就是页面回发后又会在地址栏显示出重写前的地址,也就是真实的地址,影响美观:)。有两种方法可以解决这个问题:
- 自定义一个继承form控件的控件
- [code="c#"]
1: public class Form : System.Web.UI.HtmlControls.HtmlForm 2: { 3: /// <summary> 4: /// The RenderAttributes method adds the attributes to the rendered <form> tag. 5: /// We override this method so that the action attribute is not emitted. 6: /// </summary> 7: protected override void RenderAttributes(HtmlTextWriter writer) 8: { 9: // write the form's name 10: writer.WriteAttribute("name", this.Name); 11: base.Attributes.Remove("name"); 12: 13: // write the form's method 14: writer.WriteAttribute("method", this.Method); 15: base.Attributes.Remove("method"); 16: 17: // remove the action attribute 18: base.Attributes.Remove("action"); 19: 20: // finally write all other attributes 21: this.Attributes.Render(writer); 22: 23: if (base.ID != null) 24: writer.WriteAttribute("id", base.ClientID); 25: } 26: 27: }[/code]这个方法直接去掉了form的action属性,所以页面就直接回发给自己了,能够解决问题,但使用起来比较麻烦。想象一下在每个需要重写URL的页面都要去改写form标记,够崩溃的了。
- 利用ASP.NET 2.0控件适配器扩展架构来定制控件的输出
在ASP.NET 2.0中,有个比较干净的诀窍可以用来重写<form>控件的action属性。具体地来说,利用新的ASP.NET 2.0控件适配器扩展架构来定制控件的输出,用提供的值来覆盖action属性的值。这不要求在.aspx页面里做任何编码改动,而只要在/app_browsers文件夹里添加一个.browser文件,注册使用一个控件适配类即可输出新的action属性。
.browser文件
1: <browsers> 2: <browser refID="Default"> 3: <controlAdapters> 4: <adapter controlType="System.Web.UI.HtmlControls.HtmlForm" 5: adapterType="URLRewriter.Form.FormRewriterControlAdapter" /> 6: </controlAdapters> 7: </browser> 8: </browsers>URLRewriter.Form.cs文件
[code="c#"]
1: public class FormRewriterControlAdapter : System.Web.UI.Adapters.ControlAdapter 2: { 3: public FormRewriterControlAdapter() 4: { 5: } 6: 7: protected override void Render(HtmlTextWriter writer) 8: { 9: base.Render(new RewriteFormHtmlTextWriter(writer)); 10: } 11: } 12: 13: public class RewriteFormHtmlTextWriter : HtmlTextWriter 14: { 15: public RewriteFormHtmlTextWriter(HtmlTextWriter writer) 16: : base(writer) 17: { 18: base.InnerWriter = writer.InnerWriter; 19: } 20: public RewriteFormHtmlTextWriter(System.IO.TextWriter writer) 21: : base(writer) 22: { 23: base.InnerWriter = writer; 24: } 25: 26: public override void WriteAttribute(string name, string value, bool fEncode) 27: { 28: //If the attribute we are writing is the "action" attribute, and we are not on a sub-control, 29: //then replace the value to write with the raw URL of the request - which ensures that we'll 30: //preserve the PathInfo value on postback scenarios 31: if (name == "action") 32: { 33: HttpContext context = HttpContext.Current; 34: if (context.Items["ActionAlreadyWritten"] == null) 35: { 36: //We will use the Request.RawUrl property within ASP.NET to retrieve the origional 37: //URL before it was re-written. 38: value = context.Request.RawUrl; 39: //Indicate that we've already rewritten the <form>'s action attribute to prevent 40: //us from rewriting a sub-control under the <form> control 41: context.Items["ActionAlreadyWritten"] = true; 42: } 43: } 44: base.WriteAttribute(name, value, fEncode); 45: } 46: }[/code]评论
<urlMappings enabled="true">
<add url="~/Category.aspx" mappedUrl="~/Default.aspx?category=default"/>
<add url="~/Autos.aspx" mappedUrl="~/Default.aspx?category=autos"/>
<add url="~/Games.aspx" mappedUrl="~/Default.aspx?category=games"/>
<add url="~/Health.aspx" mappedUrl="~/Default.aspx?category=health"/>
<add url="~/News.aspx" mappedUrl="~/Default.aspx?category=news"/>
</urlMappings>
在web.config配置文件中的这个url重写觉得很不错
发表评论
提醒: 该博客已发表在公共论坛,博客所有留言会成为论坛回贴,留言请注意遵守论坛发贴规则
- 浏览: 1398 次

- 详细资料
搜索本博客
最近加入圈子
最新评论
-
在ASP.NET 2.0中实现URL ...
不知道这样的方式和ISAPI的插件模式,在效率上有什么差别。
-- by 风中独火 -
在ASP.NET 2.0中实现URL ...
<system.web> <urlMappings enabl ...
-- by hunter001201 -
向页面传值接收不到
没人知道吗`````````````````````问题已经解决`````
-- by litoueva






评论排行榜