您的位置:首页 > 编程语言 > ASP

在ASP.NET 2.0中实现URL重写

2011-09-16 12:40 411 查看
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时调用此方法。您应当在此处执行所有最终的清除操作。

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:          }


注意:如果要使用窗体身份验证而不使用Windows身份验证,请将URL重写放在AuthorizeRequest事件处理程序中执行。如果要使用Windows身份验证,请在BeginRequest或AuthenticateRequest事件进行过程中安排URL重写。

在URLRewriter方法里的第7行从配置文件里读取URL重写信息,进行处理,如对正则表达式的处理。如您对如何扩展标准的配置文件还不清楚,请看这篇Blog:扩展.NET
2.0标准配置文件

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:          }


如果匹配,则调用RewriteUrl方法,将URL分解成路径和查询字符串两部分,以调用HttpContext.RewritePath方法来 实现URL的重写。其中对“URL资源的附加路径信息”(如:Http://www.microsoft.com/virdir/page.html /tail 的tail部分)未做处理,直接用String.Empty来表示,如您需要,可以自行扩展一下。

OK,到此为止,一个简单的URL重写程序就初步完成了,但还没有大功告成,还有一个细节的问题需要我们处理一下,就是页面回发后又会在地址栏显示出重写前的地址,也就是真实的地址,影响美观:)。有两种方法可以解决这个问题:
自定义一个继承form控件的控件

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:      }


这个方法直接去掉了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文件

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:      }

直接将action属性的值赋予成URL重写后的地址,简单又实惠,何乐而不为呢。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息