程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> ASP.NET >> 關於ASP.NET >> 重提URL Rewrite(3):在URL Rewrite後保持PostBack地址

重提URL Rewrite(3):在URL Rewrite後保持PostBack地址

編輯:關於ASP.NET

在進行了URL Rewrite之後,經常會遇到的問題就是頁面中PostBack的目標地址並非客戶端請求的地址,而是URL Rewrite之後的地址。以上一篇文章中的重寫為例:

<rewriter>
 <rewrite url="^/User/(\d+)$" to="~/User.aspx?id=$1" processing="stop" />
 <rewrite url="^/User/(\w+)$" to="~/User.aspx?name=$1" processing="stop" />
</rewriter>

當用戶請求“/User/jeffz”之後,頁面中的出現的代碼卻會是<form action="/User.aspx?name=jeffz" />,這是因為在生成代碼時,頁面會使用當前Request.Url.PathAndQuery的值來得到form元素的action。這導致了一旦PostBack,地址欄裡就會出現“User.aspx?name=jeffz”,而這個地址很可能是請求不到正確的資源的(因為可能被Rewrite到了別處,或者由於目錄級別的關系而根本沒有該資源)。在之前《UpdatePanel與UrlRewrite》一文中,我說可以在頁面末尾添加一行JavaScript代碼來解決這個問題:

<script language="javascript" type="text/javascript">
  document.getElementsByTagName("form")[0].action = window.location;
</script>

這行代碼的意圖非常明顯,將form的action修改為window.location(即浏覽器地址欄中的路徑),這樣當頁面進行PostBack時,目標地址就會是URL Rewrite之前的地址了。這種做法能夠讓程序正常運行,但是實在不能讓我滿意。為什麼?

因為太丑了。

因為我們還是把URL Rewrite之後的地址暴露給了客戶端。用戶只要裝一個HTTP嗅探器(例如著名的Fiddler),或者在IE中直接選擇查看源文件,我們的目標地址就毫無遮掩的顯示在用戶面前了。怎麼能讓用戶知道我們的重寫規則?我們必須解決這個問題。解決的方法很簡單,也已經非常流行了,那就是使用Control Adaptor來改變Form生成時的行為。不過讓我感到比較奇怪的是,關於這個Control Adaptor,在網絡上搜到的盡是VB.NET的版本,倒是微軟主推的C#語言卻找不到。雖然只要了解一點VB.NET的語法要改寫起來並不困難,但是畢竟也是個額外的工作啊。所以我現在就將這個Adaptor的C#版本代碼貼出來,以便朋友們能夠直接使用:

  namespace Sample.Web.UI.Adapters
  {
  public class FormRewriterControlAdapter :
  System.Web.UI.Adapters.ControlAdapter
  {
  protected override void Render(HtmlTextWriter writer)
  {
  base.Render(new RewriteFormHtmlTextWriter(writer));
  }
  }
  public class RewriteFormHtmlTextWriter : HtmlTextWriter
  {
  public RewriteFormHtmlTextWriter(HtmlTextWriter writer)
  : base(writer)
  {
  this.InnerWriter = writer.InnerWriter;
  }
  public RewriteFormHtmlTextWriter(TextWriter writer)
  : base(writer)
  {
  this.InnerWriter = writer;
  }
  public override void WriteAttribute(string name, string value, bool fEncode)
  {
  if (name == "action")
  {
  HttpContext context = HttpContext.Current;
  if (context.Items["ActionAlreadyWritten"] == null)
  {
  value = context.Request.RawUrl;
  context.Items["ActionAlreadyWritten"] = true;
  }
  }
  base.WriteAttribute(name, value, fEncode);
  }
  }
  }

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved