那通常我是自己寫 HttpModule 來處理,用 context.RewritePath(newPath, false); 來重寫網址,當然這些不是本文重點,因為網路上詳細的文章多的是,假設網址改寫成功,第一個會碰到的難題是,雖然可以正確的 rewrite ,但在 postback 後,網址又會回到 ?id=303&page=7,這個的解法有2種,Rickel's blog 有詳細的程式碼,我們是選了繼承改寫 HtmlForm 的方式解,一開始也好好的,雖然會因此無法切換到 design mode, 但因為我也少用該模式就算了,只是呢 ~好景不長,幾天後才然發現,原本運作正常的驗證控制項都沒作用了:( ,花了一段時間的debug 才找到原因,如果page使用驗證控制項,他的 form 會產生如下的語法 <form name="aspnetForm" method="post" onsubmit="javascript:return WebForm_OnSubmit();" id="aspnetForm">,但是改寫的 HtmlForm 不會產生 onsubmit 的部份。
1 public class RewriteForm : System.Web.UI.HtmlControls.HtmlForm {
2 protected override void RenderAttributes(HtmlTextWriter writer) {
3 writer.WriteAttribute("name", this.Name);
4 base.Attributes.Remove("name");
5
6 writer.WriteAttribute("method", this.Method);
7 base.Attributes.Remove("method");
8
9 this.Attributes.Render(writer);
10
11 base.Attributes.Remove("action");
12
13 //重新把 javascript:return WebForm_OnSubmit(); 加回 onsubmit
14 //以修正使用 RewriteForm 驗證控制項的Client驗證功能失效
15 //因為 ClientOnSubmitEvent 是Page的internal 的屬性,所以才用反射來取值
16 string clientOnSubmitEvent =
17 (string)typeof(Page).GetMethod("get_ClientOnSubmitEvent",
18 BindingFlags.Instance | BindingFlags.GetProperty | BindingFlags.NonPublic)
19 .Invoke(this.Page, null);
20 if (String.IsNullOrEmpty(clientOnSubmitEvent) == false) {
21 writer.WriteAttribute("onsubmit",
22 clientOnSubmitEvent);
23 }
24
25 if (base.ID != null)
26 writer.WriteAttribute("id", base.ClientID);
27 }
28 }