精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

ASP.NET Page那點(diǎn)事

開(kāi)發(fā) 后端
這次的博客我就打算專門(mén)談?wù)勊2贿^(guò)呢,我不打算說(shuō) 在Page中使用控件的一些話題,也不會(huì)說(shuō)Page的生命周期的相關(guān)話題,因?yàn)槲艺J(rèn)為這些話題被人談?wù)摰拇螖?shù)實(shí)在是太多了,尤其是市面上的ASP.NET的書(shū)籍。

Page,我想每個(gè)ASP.NET開(kāi)發(fā)人員對(duì)它應(yīng)該都是比較熟悉的。

這次的博客我就打算專門(mén)談?wù)勊2贿^(guò)呢,我不打算說(shuō) 在Page中使用控件的一些話題,也不會(huì)說(shuō)Page的生命周期的相關(guān)話題,因?yàn)槲艺J(rèn)為這些話題被人談?wù)摰拇螖?shù)實(shí)在是太多了,尤其是市面上的ASP.NET的書(shū)籍,都會(huì)比較喜歡這些話題。

我不喜歡重復(fù),因此今天我只想談些人家不談的那點(diǎn)事,但我認(rèn)為它們?nèi)匀缓苤匾?/p>

一些重要的Page指令

雖然Page公開(kāi)了很多屬性,讓我們可以在運(yùn)行時(shí)調(diào)整它的狀態(tài)與行為,但是,還有些重要的參數(shù)卻是以“指令”方式提供的,需要在設(shè)計(jì)時(shí)就指定。

下面是我整理的一些我認(rèn)為 比較重要并且經(jīng)常需要使用的指令:

#p#

web.config的全局設(shè)置

前面我介紹了一些常用的Page指令,考慮到方便性,ASP.NET還允許我們?cè)趙eb.config中為一些常用的指令配置默認(rèn)值。下面我就一些常用的場(chǎng)景來(lái)說(shuō)明這些全局配置的方便性。

1. 通常,我在創(chuàng)建一個(gè)網(wǎng)站項(xiàng)目時(shí),肯定會(huì)決定不使用ViewState和Session的。那么如果為每個(gè)頁(yè)面設(shè)置EnableViewState,EnableSessionState指令屬性,那就顯得太麻煩了,而且還容易遺漏。此時(shí),我們可以直接在web.config中為這些參數(shù)指定一個(gè)全局的默認(rèn)值:

  1. <pages enableViewState="false" enableSessionState="false"></pages> 
  2.  

補(bǔ)充說(shuō)明一下:全局禁用Session的徹底方法是把Session對(duì)應(yīng)的HttpModule從httpModules列表中移除。

web.config允許我們?cè)O(shè)置Page默認(rèn)參數(shù)的具體配置節(jié)如下:

  1. <pages       
  2.    buffer="[True|False]" 
  3.    enableEventValidation="[True|False]" 
  4.    enableSessionState="[True|False|ReadOnly]" 
  5.    enableViewState="[True|False]" 
  6.    enableViewStateMac="[True|False]" 
  7.    smartNavigation="[True|False]" 
  8.    autoEventWireup="[True|False]" 
  9.    pageBaseType="typename, assembly" 
  10.    userControlBaseType="typename" 
  11.    validateRequest="[True|False]" 
  12.    masterPageFile="file path"   
  13.    theme="string" 
  14.    styleSheetTheme="string" 
  15.    maxPageStateFieldLength="number"   
  16.    compilationMode="[Always|Auto|Never]"   
  17.    pageParserFilterType="string"   
  18.    viewStateEncryptionMode="[Always|Auto|Never]"   
  19.    maintainScrollPositionOnPostBack="[True|False]"   
  20.    asyncTimeout="number" 
  21. > 
  22.    <controls>...</controls> 
  23.    <namespaces>...</namespaces> 
  24.    <tagMapping>...</tagMapping> 
  25. </pages> 

2. 為了代碼重用,設(shè)計(jì)用戶控件也是很常用的方法。

我們可以使用 @ Register指令 在頁(yè)面注冊(cè)需要使用的UserControl或者WebControl。然而,有些控件比較通用,許多頁(yè)面都會(huì)使用它,那么就不要再使用 @ Register指令了,可以在web.config中統(tǒng)一注冊(cè)。例如:

  1. <pages> 
  2.     <controls> 
  3.         <add tagPrefix="fish" tagName="MainMenu" src="~/Controls/MainMenu.ascx" /> 
  4.         <add tagPrefix="fish" tagName="PageHeader" src="~/Controls/PageHeader.ascx" /> 
  5.     </controls> 
  6. </pages> 

有了這個(gè)定義后,我就可以在任何頁(yè)面中直接使用:

  1. <fish:PageHeader runat="server" ID="PageHeader1" /> 

3. 對(duì)于喜歡使用頁(yè)面內(nèi)聯(lián)代碼的人來(lái)說(shuō),可能經(jīng)常需要使用自己定義的類型。如果這些類型定義在某個(gè)命名空間中,那么就需要在內(nèi)聯(lián)代碼中采用完整命名空間的寫(xiě)法。雖然這樣做沒(méi)有什么問(wèn)題,但就是麻煩,于是,我們可以在頁(yè)面中使用 @ Import指令 來(lái)導(dǎo)入我們需要使用的命名空間,但是這個(gè)指令每次只能導(dǎo)入一個(gè)命名空間,而且每個(gè)頁(yè)面還得重復(fù)導(dǎo)入,顯然不夠方便。

為了方便使用一些常用的命名空間,我們可以在web.config中統(tǒng)一指定,例如:

  1. <pages> 
  2.     <namespaces> 
  3.         <add namespace="MyMVC" /> 
  4.         <add namespace="WebSiteCommonLib" /> 
  5.         <add namespace="WebSiteModel" /> 
  6.     </namespaces> 
  7. </pages> 

這樣設(shè)置后,所有頁(yè)面就可以直接使用這些命名空間下的類型了。

不知道有些人想過(guò):為什么在頁(yè)面中使用某些微軟提供的類型就不需要導(dǎo)入命名空間?

答案是:其實(shí)ASP.NET已經(jīng)將一些微軟認(rèn)為常用的命名空間在web.config中配置好了:

  1. <pages> 
  2.     <namespaces> 
  3.         <add namespace="System"/> 
  4.         <add namespace="System.Collections"/> 
  5.         <add namespace="System.Collections.Specialized"/> 
  6.         <add namespace="System.Configuration"/> 
  7.         <add namespace="System.Text"/> 
  8.         <add namespace="System.Text.RegularExpressions"/> 
  9.         <add namespace="System.Web"/> 
  10.         <add namespace="System.Web.Caching"/> 
  11.         <add namespace="System.Web.SessionState"/> 
  12.         <add namespace="System.Web.Security"/> 
  13.         <add namespace="System.Web.Profile"/> 
  14.         <add namespace="System.Web.UI"/> 
  15.         <add namespace="System.Web.UI.WebControls"/> 
  16.         <add namespace="System.Web.UI.WebControls.WebParts"/> 
  17.         <add namespace="System.Web.UI.HtmlControls"/> 
  18.     </namespaces> 
  19. </pages> 

4. 現(xiàn)在,有越來(lái)越多的人為了方便而使用擴(kuò)展方法。使用擴(kuò)展方法的好處是:可以讓我們不去關(guān)心這些擴(kuò)展方法定義在那個(gè)類中,只要在支持?jǐn)U展方法的對(duì)象上調(diào)用就可以了,就像下面的代碼這樣:

  1. 當(dāng)前用戶已登錄,登錄名:<%= Context.User.Identity.Name.HtmlEncode() %> 

然而,在頁(yè)面中使用擴(kuò)展方法時(shí),也必須先導(dǎo)入擴(kuò)展方法的定義類的命名空間。

因此,為了方便,我們可以在web.config中為我們定義的擴(kuò)展方法導(dǎo)入相應(yīng)的命名空間:

  1. <pages> 
  2.     <namespaces> 
  3.         <add namespace="FishDemoCodeLib" /> 
  4.     </namespaces> 
  5. </pages> 

#p#

換個(gè)方式使用 Page

在傳統(tǒng)的WEB開(kāi)發(fā)模式下,我們通常會(huì)設(shè)計(jì)一些頁(yè)面(Page)響應(yīng)來(lái)自用戶瀏覽器的請(qǐng)求,在這種模式下,Page會(huì)將***生成的整頁(yè)HTML代碼直接發(fā)送給用戶瀏覽器。然而,在某些時(shí)候,我們只需要生成一個(gè)HTML片段:

1. 在AJAX請(qǐng)求中,客戶端為了局部刷新,只要求服務(wù)端返回一個(gè)HTML片段。

2. BigPipe方式下,為了能分塊輸出,每次也只需要輸出一個(gè)HTML片段。

如果只是為了得到一段簡(jiǎn)單的HTML代碼,可能有些人會(huì)選擇采用代碼來(lái)拼接,但是如果那段HTML還有些復(fù)雜呢?顯然拼接方法肯定是不行的。

對(duì)于***個(gè)問(wèn)題,可能有人說(shuō):我可以創(chuàng)建一個(gè)頁(yè)面,只放部分代碼到頁(yè)面上。的確,這種方法可以勉強(qiáng)解決***個(gè)問(wèn)題,但是,很有可能那部分代碼在整頁(yè)輸出時(shí)也會(huì)用到,怎么辦?

做成UserControl,然后放在一個(gè)單獨(dú)的頁(yè)面中!其實(shí)這種做法很無(wú)奈,因?yàn)槟莻€(gè)容器頁(yè)面的意義不大(僅僅是個(gè)容器),***搞得項(xiàng)目中一大堆頁(yè)面文件!事實(shí)上,這種方法僅適用于使用簡(jiǎn)單服務(wù)端控件的場(chǎng)合,如果想使用一些高級(jí)的服務(wù)端控件,它根本就不行。

為了能實(shí)現(xiàn)前面說(shuō)到的二個(gè)需求,我們就不能再按照傳統(tǒng)的方式來(lái)使用Page了。因?yàn)槲覀兿M艿玫剑ǚ祷兀┮欢蜨TML。

有二種方法可以讓我們繼續(xù)使用頁(yè)面模板代碼的方式生成HTML代碼:

1. Server.Execute()方法。

2. Page.RenderControl()方法。

下面這段代碼來(lái)源于 MyMVC框架,這個(gè)方法可以根據(jù)指定的用戶控件以及控件顯示所需的數(shù)據(jù)得到控件的輸出結(jié)果(一段HTML代碼)。

  1. /// <summary> 
  2. /// 用指定的用戶控件以及視圖數(shù)據(jù)呈現(xiàn)結(jié)果,***返回生成的HTML代碼。  
  3. /// 用戶控件應(yīng)從MyUserControlView<T>繼承  
  4. /// </summary> 
  5. /// <param name="ucVirtualPath">用戶控件的虛擬路徑</param> 
  6. /// <param name="model">視圖數(shù)據(jù)</param> 
  7. /// <returns>生成的HTML代碼</returns> 
  8. public static string Render(string ucVirtualPath, object model)  
  9. {  
  10.     if( string.IsNullOrEmpty(ucVirtualPath) )  
  11.         throw new ArgumentNullException("ucVirtualPath");  
  12.       
  13.     Page page = new Page();  
  14.     Control ctl = page.LoadControl(ucVirtualPath);  
  15.     if( ctl == null )  
  16.         throw new InvalidOperationException(  
  17.             string.Format("指定的用戶控件 {0} 沒(méi)有找到。", ucVirtualPath));  
  18.  
  19.     if( model != null ) {  
  20.         MyBaseUserControl myctl = ctl as MyBaseUserControl;  
  21.         if( myctl != null )  
  22.             myctl.SetModel(model);  
  23.     }  
  24.  
  25.     // 將用戶控件放在Page容器中。  
  26.     page.Controls.Add(ctl);  
  27.  
  28.     StringWriter output = new StringWriter();  
  29.     HtmlTextWriter write = new HtmlTextWriter(output, string.Empty);  
  30.     page.RenderControl(write);  
  31.  
  32.     // 用下面的方法也可以的。  
  33.     //HttpContext.Current.Server.Execute(page, output, false);  
  34.  
  35.     return output.ToString();  
  36. }  

整段代碼分為以下幾個(gè)步驟(我已用空行分隔開(kāi)了):

1. 檢查參數(shù)。

2. 創(chuàng)建頁(yè)面容器并加載用戶控件。

3. 設(shè)置頁(yè)面(視圖)所需的顯示數(shù)據(jù)。

4. 將用戶控件添加到Page的Controls集合中。

5. 調(diào)用RenderControl或者Execute讓Page輸出HTML代碼。

6. 返回結(jié)果。

這段代碼很簡(jiǎn)單,唯獨(dú)值得介紹的就是第5步,調(diào)用它們就可以得到控件輸出的HTML代碼。

RenderControl或者Execute的差別在于:

RenderControl不支持服務(wù)器控件,原因在于它利用了頁(yè)面的一種獨(dú)特編譯方式,我已在以前的博客中分析過(guò)了。

Execute可以支持服務(wù)器控件,因?yàn)樗鼤?huì)執(zhí)行一次完整的頁(yè)面生命周期。

注意:上面這段代碼就算使用Execute,也只能支持部分簡(jiǎn)單的服務(wù)器控件,因?yàn)橐恍?fù)雜的服務(wù)器控件需要在HtmlForm中才能運(yùn)行。因此,如果需要支持所有的服務(wù)器控件,那么還必須創(chuàng)建HtmlForm對(duì)象,并調(diào)整包含關(guān)系,還有就是還需要去掉產(chǎn)生的多余HTML代碼。

如果你需要生成整個(gè)頁(yè)面生成的HTML代碼,可以參考 MyMVC框架,那里有實(shí)現(xiàn)這個(gè)功能的完整代碼。

#p#

重新認(rèn)識(shí)Eval()方法

我想很多人都寫(xiě)過(guò)類似下面的代碼:

  1. <asp:Repeater ID="repeater1" runat="server"> 
  2.     <HeaderTemplate><ul></HeaderTemplate> 
  3.     <FooterTemplate></ul></FooterTemplate> 
  4.     <ItemTemplate> 
  5.         <li><%# Eval("OrderID")%><%# Eval("OrderDate")%><%# Eval("SumMoney")%> 
  6.         </li> 
  7.     </ItemTemplate> 
  8. </asp:Repeater> 

在這里我要說(shuō)的是 Eval() 的調(diào)用,還不是Repeater控件。

Eval()不僅僅可以讀取一個(gè)綁定數(shù)據(jù)項(xiàng)的屬性,還可以去讀取DataTable中的一個(gè)數(shù)據(jù)列。而且還能完成更復(fù)雜的綁定計(jì)算:

  1. <li><%# Eval("OrderID")%><%# Eval("OrderDate")%><%# Eval("SumMoney")%> 
  2.     ,訂單中的***個(gè)商品:<%# Eval("Detail[0].ProductName") %> 
  3. </li> 

當(dāng)然了,對(duì)于頁(yè)面上的數(shù)據(jù)綁定,用Eval()的確不是性能***的方法,建議還是使用強(qiáng)類型轉(zhuǎn)換的方法。

有時(shí)候,尤其是在寫(xiě)反射應(yīng)用時(shí),時(shí)常會(huì)有從字符串解析并實(shí)現(xiàn)求值計(jì)算的需求。那么,前面這個(gè)示例中,Eval()的功能是不是值得挖掘呢?我認(rèn)為答案是肯定的。

通過(guò)分析ASP.NET的綁定代碼,我發(fā)現(xiàn)Eval在內(nèi)部會(huì)調(diào)用DataBinder.Eval這個(gè)靜態(tài)方法,這個(gè)方法的簽名如下:

  1. //     在運(yùn)行時(shí)計(jì)算數(shù)據(jù)綁定表達(dá)式。  
  2. //  
  3. // 參數(shù):  
  4. //   container:  
  5. //     表達(dá)式根據(jù)其進(jìn)行計(jì)算的對(duì)象引用。此標(biāo)識(shí)符必須是以頁(yè)的指定語(yǔ)言表示的有效對(duì)象標(biāo)識(shí)符。  
  6. //  
  7. //   expression:  
  8. //     從 container 到要放置在綁定控件屬性中的公共屬性值的導(dǎo)航路徑。  
  9. //     此路徑必須是以點(diǎn)分隔的屬性或字段名稱字符串,如 C# 中的 "Tables[0].DefaultView.[0].Price"  
  10. //     或 Visual Basic 中的 "Tables(0).DefaultView.(0).Price"。  
  11. //  
  12. // 返回結(jié)果:  
  13. //     System.Object,它是數(shù)據(jù)綁定表達(dá)式的計(jì)算結(jié)果。  
  14. public static object Eval(object container, string expression);  

通過(guò)這個(gè)簽名的注釋,我們可以很容易地看出它的用法。

下面我來(lái)舉個(gè)例子把它應(yīng)用在非綁定的應(yīng)用中:

我有一個(gè)類:

  1. public class TestEvalClass  
  2. {  
  3.     public List<Order> Orders { get; set; }  
  4.  
  5.     // Order以及OrderDetail的定義就省略了,我想大家能想像得出來(lái)。  
  6. }  

那么下面的代碼是可以運(yùn)行的:

  1. static void Main()  
  2. {  
  3.     TestEvalClass testObject = GetTestEvalClassInstance();  
  4.  
  5.     string productName = (string)System.Web.UI.DataBinder.Eval(testObject, "Orders[0].Detail[0].ProductName");  
  6.     Console.WriteLine(productName);  
  7. }  

對(duì)于這個(gè)示例,我想輸出什么結(jié)果,并不重要。

我只想說(shuō):如果讓你去解析那個(gè)表達(dá)式,會(huì)不會(huì)比較麻煩,現(xiàn)在有現(xiàn)成的,用起來(lái)是不是很方便?

#p#

不用基類也能擴(kuò)展

在一個(gè)ASP.NET網(wǎng)站中,如果想為所有的頁(yè)面添加某個(gè)功能,我們通常會(huì)想到使用基類的方式去實(shí)現(xiàn)。這的確是一種很有效的方法,但不并唯一的方法,還有一種方法也能容易實(shí)現(xiàn)這個(gè)需求,那就是使用PageAdapter的方式。

在我寫(xiě)博客的過(guò)程中,我寫(xiě)了很多示例頁(yè)面,頁(yè)面中包含一些提交按鈕是少不了的事情,然而,為了能讓示例代碼看起來(lái)比較原始(簡(jiǎn)單),我盡量不使用服務(wù)器控件,因此就要面臨提交按鈕的事件處理問(wèn)題。在博客【細(xì)說(shuō) ASP.NET Cache 及其高級(jí)用法】的示例代碼中,我開(kāi)始采用PageAdapter這種方法,它可以讓代碼很簡(jiǎn)單,而且以后也方便以后重用(只需要復(fù)制幾個(gè)文件即可)。

或許有些人認(rèn)為:擴(kuò)展所有頁(yè)面的功能,還是使用基類比較好。

對(duì)于這個(gè)觀點(diǎn),我完全不反對(duì)。

但是,PageAdapter的好處在于它的可插拔性(類似HttpModule的優(yōu)點(diǎn))。不過(guò),我當(dāng)時(shí)設(shè)計(jì)這種擴(kuò)展方式只是想再換個(gè)方法嘗試一下而已。

其實(shí)微軟設(shè)計(jì)PageAdapter的本意是為了處理各種瀏覽器的兼容問(wèn)題,但是我把這個(gè)功能用到擴(kuò)展Page的功能上去了。 HttpModule可以進(jìn)入到ASP.NET請(qǐng)求管線的任何階段,但它就是進(jìn)入不了頁(yè)面的生命周期中,有了這個(gè)方法,我們就可以采用HttpModule這種【外掛】式的方法進(jìn)入到頁(yè)面生命周期中,我認(rèn)為是很有意義的。

方法多了,我想不是件壞事。每種方法都有適合它們的應(yīng)用場(chǎng)合,了解更多的方法,以后就能做出更優(yōu)秀的設(shè)計(jì)。

這次想到這個(gè)話題是因?yàn)榍懊娴牟┛汀炯?xì)說(shuō)ASP.NET Forms 身份認(rèn)證】中的示例代碼。有些人看到那些代碼,發(fā)現(xiàn)代碼的運(yùn)行方式比較特別,所以,今天我就打算著重介紹這種方法。

我們?cè)賮?lái)回顧一下以前博客中的示例代碼,首先從頁(yè)面代碼開(kāi)始:

  1. <fieldset><legend>普通登錄</legend><form action="<%= Request.RawUrl %>" method="post"> 
  2.     登錄名:<input type="text" name="loginName" style="width: 200px" value="Fish" /> 
  3.     <input type="submit" name="NormalLogin" value="登錄" /> 
  4. </form></fieldset> 
  5.    
  6. <fieldset><legend>包含【用戶信息】的自定義登錄</legend>    <form action="<%= Request.RawUrl %>" method="post"> 
  7.     <table border="0"> 
  8.     <tr><td>登錄名:</td> 
  9.         <td><input type="text" name="loginName" style="width: 200px" value="Fish" /></td></tr> 
  10.     <tr><td>UserId:</td> 
  11.         <td><input type="text" name="UserId" style="width: 200px" value="78" /></td></tr> 
  12.     <tr><td>GroupId:</td> 
  13.         <td><input type="text" name="GroupId" style="width: 200px" /> 
  14.         1表示管理員用戶  
  15.         </td></tr> 
  16.     <tr><td>用戶全名:</td> 
  17.         <td><input type="text" name="UserName" style="width: 200px" value="Fish Li" /></td></tr> 
  18.     </table>      
  19.     <input type="submit" name="CustomizeLogin" value="登錄" /> 
  20. </form></fieldset> 

在這段頁(yè)面代碼中,我定義了二個(gè)表單,它們包含各自的提交按鈕(其實(shí)這也只是部分代碼)。

再來(lái)看后臺(tái)處理代碼是如何響應(yīng)提交請(qǐng)求的:

  1. public partial class _Default : System.Web.UI.Page   
  2. {  
  3.     [SubmitMethod(AutoRedirect = true)]  
  4.     public void NormalLogin()  
  5.     {  
  6.         // 省略登錄處理代碼。  
  7.         // 如果需要知道這段代碼可以瀏覽下面的網(wǎng)址:  
  8.         // http://www.cnblogs.com/fish-li/archive/2012/04/15/2450571.html   
  9.     }  
  10.  
  11.     [SubmitMethod(AutoRedirect = true)]  
  12.     public void CustomizeLogin()  
  13.     {  
  14.         // 省略登錄處理代碼。  
  15.         // 如果需要知道這段代碼可以瀏覽下面的網(wǎng)址:  
  16.         // http://www.cnblogs.com/fish-li/archive/2012/04/15/2450571.html   
  17.     }  

注意觀察,這二個(gè)C#方法的名稱與頁(yè)面二個(gè)submit按鈕的name屬性相同,因此可以猜測(cè)到這二個(gè)C#方法可以處理那二個(gè)submit按鈕的提交請(qǐng)求。那么這二段代碼是如何運(yùn)行起來(lái)的呢?有些人或許看到了[SubmitMethod]的使用,認(rèn)為與它們有關(guān)。其實(shí)這種說(shuō)法并不正確,我也可以完全不使用它們。請(qǐng)記住:Attribute永遠(yuǎn)只是一個(gè)標(biāo)記,它不可能讓代碼自動(dòng)運(yùn)行起來(lái)。

前面的代碼能運(yùn)行起來(lái),與App_Browsers目錄下的Page.browser文件有關(guān),此文件的代碼如下:

  1. <browsers> 
  2.     <browser refID="Default"> 
  3.         <controlAdapters> 
  4.             <adapter controlType="System.Web.UI.Page" 
  5.                      adapterType="FishDemoCodeLib.MyPageAdapter, FishDemoCodeLib" /> 
  6.         </controlAdapters> 
  7.     </browser> 
  8. </browsers> 

這里定義了一個(gè)MyPageAdapter,它用于Page控件的請(qǐng)求過(guò)程。 refID="Default" 表示是對(duì)ASP.NET定義的Default.browser文件補(bǔ)充一些配置,它將能匹配來(lái)自所有瀏覽器的請(qǐng)求。

我再來(lái)看一下MyPageAdapter的代碼:

  1. [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]  
  2. public class SubmitMethodAttribute : Attribute  
  3. {  
  4.     public bool AutoRedirect { get; set; }  
  5. }  
  6.  
  7. internal sealed class MethodInvokeInfo  
  8. {  
  9.     public MethodInfo MethodInfo;  
  10.     public SubmitMethodAttribute MethodAttribute;  
  11. }  
  12.  
  13. public class MyPageAdapter : System.Web.UI.Adapters.PageAdapter  
  14. {  
  15.     private static readonly Hashtable s_table = Hashtable.Synchronized(new Hashtable());  
  16.  
  17.     private static MethodInvokeInfo[] GetMethodInfo(Type type)  
  18.     {  
  19.         MethodInvokeInfo[] array = s_table[type.AssemblyQualifiedName] as MethodInvokeInfo[];  
  20.         if( array == null ) {  
  21.             array = (from m in type.GetMethods(BindingFlags.Instance | BindingFlags.Public)  
  22.                      let a = m.GetCustomAttributes(  
  23.                             typeof(SubmitMethodAttribute), false) as SubmitMethodAttribute[]  
  24.                      where a.Length > 0  
  25.                      select new MethodInvokeInfo {   
  26.                             MethodInfo = mMethodAttribute = a[0] }).ToArray();  
  27.  
  28.             s_table[type.ToString()] = array;  
  29.         }  
  30.         return array;  
  31.     }  
  32.  
  33.  
  34.     protected override void OnLoad(EventArgs e)  
  35.     {  
  36.         base.OnLoad(e);  
  37.  
  38.         if( Page.Request.Form.AllKeys.Length == 0 )  
  39.             return;    // 沒(méi)有提交表單  
  40.  
  41.         MethodInvokeInfo[] array = GetMethodInfo(Page.GetType().BaseType);  
  42.         if( array.Length == 0 )  
  43.             return;  
  44.  
  45.         foreach( MethodInvokeInfo m in array ) {  
  46.             if( string.IsNullOrEmpty(Page.Request.Form[m.MethodInfo.Name]) == false ) {  
  47.                 m.MethodInfo.Invoke(Page, null);  
  48.  
  49.                 if( m.MethodAttribute.AutoRedirect   
  50.                                 && Page.Response.IsRequestBeingRedirected == false )  
  51.                     Page.Response.Redirect(Page.Request.RawUrl);  
  52.  
  53.                 return;  
  54.             }  
  55.         }  
  56.     }  
  57. }  

這段代碼并不長(zhǎng),核心代碼更是比較少。

代碼中,最重要的一塊是MyPageAdapter的實(shí)現(xiàn),它繼承了System.Web.UI.Adapters.PageAdapter,并重寫(xiě)了OnLoad方法(相當(dāng)是在重寫(xiě)Page的OnLoad方法),也正是由于這個(gè)重寫(xiě),代碼才有機(jī)會(huì)在頁(yè)面的生命周期中被執(zhí)行,這一點(diǎn)是HttpModule做不到的。

在OnLoad方法中做了以下事情:

1. 檢查是不是發(fā)生了表單提交的操作。

2. 獲取當(dāng)前頁(yè)面類型的所有[SubmitMethod]修飾過(guò)的方法。

3. 檢查提交的表單數(shù)據(jù)中,是否存在與name對(duì)應(yīng)的C#方法名。

4. 如果找到一個(gè)匹配的方法名,則調(diào)用。

5. 如果在[SubmitMethod]中設(shè)置了AutoRedirect=true,則引發(fā)重定向。

注意:如果不調(diào)用base.OnLoad(e); 那么頁(yè)面的Load事件根本不會(huì)發(fā)生。也就是說(shuō):PageAdapter.OnLoad的調(diào)用時(shí)間要早于Page.Onload方法。

由于這段代碼僅供我寫(xiě)示例代碼時(shí)使用,因此并沒(méi)有檢查要調(diào)用的方法的參數(shù)是否滿足條件,也沒(méi)有優(yōu)化刻意去優(yōu)化它的性能。在我的設(shè)計(jì)中,被調(diào)用的方法應(yīng)該是無(wú)參的,因此是容易判斷的,而且可以使用一個(gè)固定簽名的委托去優(yōu)化它的,這些細(xì)節(jié)留著以后再去完善它吧!

 

原文鏈接:http://www.cnblogs.com/fish-li/archive/2012/06/10/2544087.html

責(zé)任編輯:張偉 來(lái)源: Fish Li的博客
相關(guān)推薦

2009-08-07 16:45:09

ASP.NET頁(yè)面對(duì)象

2009-07-23 14:47:03

Page_Load方法ASP.NET

2009-08-04 17:49:31

Web Page生命周ASP.NET Pos

2009-08-03 14:22:33

什么是ASP.NET

2009-07-28 17:17:19

ASP.NET概述

2009-07-22 17:45:35

ASP.NET教程

2010-05-06 17:46:47

2009-07-27 12:22:03

ASP.NET和ASPASP.NET入門(mén)教程

2009-08-10 13:32:15

ASP.NET TimASP.NET組件設(shè)計(jì)

2009-07-29 17:11:25

ASP.NET ISA

2021-04-26 14:25:39

ASP.NET Cor單元測(cè)試

2009-07-29 16:08:07

ASP和ASP.NET

2009-07-28 09:02:32

asp.net aja

2009-08-03 17:35:07

ASP.NET WebASP.NET編程工具

2009-08-03 13:38:18

ASP.NET編程模型

2009-07-27 15:52:21

ASP.NET特點(diǎn)ASP.NET概述

2009-07-31 10:23:44

緩存頁(yè)面ASP.NET緩存

2009-07-27 10:35:33

TypeConvertASP.NET

2009-07-23 13:19:51

2009-07-27 14:46:16

XML和ASP.NET
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

在线观看欧美| 久操视频在线免费播放| 欧美亚洲三区| 中文字幕精品—区二区| 亚洲涩涩在线观看| 波多野结依一区| 日本一区二区三区国色天香| 91九色露脸| 欧美 日韩 精品| 亚洲精品国产首次亮相| 亚洲精品久久久久中文字幕二区| 少妇黄色一级片| xxxx视频在线| ●精品国产综合乱码久久久久| 国产精品一级久久久| 午夜视频网站在线观看| 欧美视频导航| 色偷偷偷综合中文字幕;dd| 免费观看污网站| 欧美大片网站| 色一情一乱一乱一91av| 黄色一级片国产| 东凛在线观看| 不卡电影一区二区三区| 国产在线久久久| 亚洲伊人成人网| 欧美日韩精品| 久久好看免费视频| 国产肥白大熟妇bbbb视频| 最新国产精品精品视频| 欧美日韩国产综合视频在线观看 | 亚洲制服中文字幕| 亚洲人成在线网站| 亚洲国产毛片aaaaa无费看| 一区二区欧美日韩| 国产中文字幕在线| 91香蕉视频在线| 国产精品污www一区二区三区| 亚洲熟女乱色一区二区三区久久久| av不卡在线| 欧美黑人巨大精品一区二区| 欧美色视频一区二区三区在线观看| 丝袜连裤袜欧美激情日韩| 欧美成人vr18sexvr| 污污网站在线观看视频| 日韩在线免费| 在线免费视频一区二区| 免费黄色福利视频| 人人草在线视频| 亚洲成人免费观看| 亚洲色成人www永久在线观看| 最新国产露脸在线观看| 亚洲视频一区二区在线观看| 亚洲一区二区在线看| 风间由美一区| 日本一区二区三区国色天香| 日韩亚洲欧美精品| 川上优的av在线一区二区| 久久久久久久久97黄色工厂| 成人自拍偷拍| 丰满熟妇乱又伦| 成人午夜av电影| 国产一区福利视频| 四虎精品在线| 国产日产欧美精品一区二区三区| 欧美精品一区二区三区在线四季 | 一二三区中文字幕| 久久国产人妖系列| 成人午夜小视频| 国产黄色片免费观看| 国产成人在线视频播放| 国产乱码精品一区二区三区日韩精品| 亚洲第一视频在线| 成人av电影免费观看| 国产综合欧美在线看| 青青青草原在线| 亚洲国产精品v| 免费国产成人看片在线| 男女羞羞视频在线观看| 午夜av电影一区| 日本熟妇人妻中出| www.久久99| 亚洲电影在线观看| 扒开jk护士狂揉免费| 日韩精品看片| 欧美日韩第一页| www成人在线| 蜜臀av性久久久久蜜臀aⅴ流畅| 国产一区视频在线播放| 不卡视频在线播放| 久久久久国产精品厨房| 国产日本欧美在线| 大桥未久在线视频| 欧美三级电影网站| 极品白嫩的小少妇| 激情五月综合| 欧美激情国产日韩精品一区18| 国产精品久久久久久久久久久久久久久久久 | 性欧美在线看片a免费观看| 亚洲熟妇无码乱子av电影| 久久精品噜噜噜成人av农村| julia一区二区中文久久94| 日色在线视频| 亚洲精品日产精品乱码不卡| 成人在线看视频| 美国十次综合久久| 亚洲欧美日韩在线高清直播| 欧美三级日本三级| 视频一区视频二区中文字幕| www.一区二区三区| 最新97超碰在线| 亚洲国产va精品久久久不卡综合| 成人午夜激情av| 高清一区二区三区| xxx成人少妇69| 无码aⅴ精品一区二区三区| 丁香另类激情小说| 亚洲一区二区高清视频| 伊人久久视频| 欧美精品一区二区三区蜜桃| 日韩一区二区三区四区视频| 先锋影音久久久| 成人精品水蜜桃| 麻豆传媒在线免费看| 日韩欧美在线观看视频| 69xxx免费视频| 国产精品久久久乱弄| 国产不卡av在线| 少妇精品视频一区二区| 亚洲乱码国产乱码精品精98午夜| 久热精品在线观看视频| 国产成人一区| 欧美一二三视频| 日本黄色不卡视频| 亚洲综合在线第一页| www.久久久久久久久久久| 成人同人动漫免费观看| 日av在线播放中文不卡| 手机在线不卡av| 亚洲成人av在线电影| 日韩av福利在线观看| 小处雏高清一区二区三区| 国产精品视频网址| 尤物视频在线免费观看| 91久久精品一区二区二区| 欧美色图亚洲激情| 国产精品一国产精品k频道56| 国产三级精品在线不卡| 欧美男男video| 国产99亚洲| 免费观看在线综合色| 国模一区二区三区私拍视频| 高清电影在线观看免费| 精品国产乱码久久久久久久| 久久伊人成人网| 国产成人精品亚洲777人妖| 粉嫩av一区二区三区天美传媒 | 欧美片第1页综合| 成人免费视频a| 在线欧美三级| 精品毛片乱码1区2区3区| 久草国产在线视频| www.一区二区| 黄色片视频在线播放| 狠狠色丁香婷婷综合影院| 国产精品av在线| eeuss影院www在线播放| 欧美乱妇15p| 黄色一级视频在线观看| 不卡av免费在线观看| 97成人在线观看视频| 国产精品欧美日韩一区| 国产精品在线看| av在线下载| 亚洲精品成人久久久| 国产一卡二卡三卡| 最近中文字幕一区二区三区| 欧美老女人bb| 一区二区久久| 亚洲巨乳在线观看| 免费观看亚洲视频大全| 97人人模人人爽人人喊中文字| 飘雪影院手机免费高清版在线观看 | 亚洲欧美在线一区二区| 亚洲无码久久久久| 亚洲高清三级视频| 美女被到爽高潮视频| 国内久久婷婷综合| 欧美深夜福利视频| 成人黄色小视频| 成人一区二区在线| 欧美日韩免费观看视频| 久久91精品国产91久久跳| 五月婷婷久久久| 欧美日韩久久久| 国产成人无码精品亚洲| 中文幕一区二区三区久久蜜桃| 日本中文字幕精品| 老司机精品视频网站| 女女百合国产免费网站| 亚洲黄页在线观看| 亚洲一区亚洲二区| 国产成人精品123区免费视频| 久久99久国产精品黄毛片入口| 免费观看成年在线视频网站| 欧美一区二区三区视频免费播放| 在线观看日本视频| 亚洲一区在线观看免费观看电影高清 | 欧美日韩卡一| 欧美亚洲另类在线| 在线观看午夜av| 中文字幕亚洲第一| 亚洲欧美综合在线观看| 日韩天堂在线观看| 免费在线不卡av| 婷婷久久综合九色综合伊人色| 国产免费一区二区三区四区| 久久综合色8888| 年下总裁被打光屁股sp| 久久精品国产一区二区三区免费看| 国产人妻777人伦精品hd| 68国产成人综合久久精品| 青青草成人激情在线| 果冻天美麻豆一区二区国产| 亚洲va码欧洲m码| 成人精品一区二区三区电影| 奇米四色中文综合久久| 精精国产xxxx视频在线中文版| 日韩最新免费不卡| 成人在线观看黄色| 亚洲精品一区久久久久久| 亚洲精品无amm毛片| 欧美一区二区三区不卡| 国产又粗又猛视频免费| 欧美伊人久久大香线蕉综合69| 中文字幕激情小说| 午夜精品久久久久久久99水蜜桃| 国产va在线播放| 亚洲四区在线观看| 美女视频久久久| 亚洲特黄一级片| 亚洲综合视频网站| 国产精品福利电影一区二区三区四区| 久久久久久久久久久久| 久久精品夜色噜噜亚洲a∨| 风间由美一二三区av片| 不卡av在线免费观看| 亚洲av成人片色在线观看高潮| 丁香六月久久综合狠狠色| aaa黄色大片| 成人高清伦理免费影院在线观看| 性感美女一区二区三区| 成人激情综合网站| 精品影片一区二区入口| 95精品视频在线| 国产精品无码一区二区三区免费 | 成年人视频软件| 国产精品久久久久久久久搜平片| 极品蜜桃臀肥臀-x88av| 国产精品国产三级国产普通话99| 国产精品视频一区二区在线观看| 一区在线观看视频| 青青草免费av| 精品国产户外野外| 最近免费中文字幕大全免费版视频| 在线视频综合导航| 一区二区日韩在线观看| 日韩一区二区在线看片| 成人毛片在线精品国产| 日韩高清免费观看| 岛国视频免费在线观看| 色偷偷综合社区| 污视频在线看网站| 91爱爱小视频k| 91看片一区| 91在线无精精品一区二区| 给我免费播放日韩视频| 日日夜夜精品网站| 婷婷成人基地| 老太脱裤子让老头玩xxxxx| 视频一区二区三区在线| 久久久久久综合网| 99re这里只有精品首页| 国产黄a三级三级| 亚洲高清一区二区三区| 手机av免费观看| 欧美成人国产一区二区| 蜜桃视频在线播放| 久久视频国产精品免费视频在线| 51漫画成人app入口| 国产精品视频一区二区高潮| 韩国一区二区三区视频| 久久久www免费人成黑人精品| 97欧美在线视频| 黄色动漫网站入口| 国内外成人在线视频| 在线免费观看成年人视频| 亚洲日本韩国一区| 天堂中文字幕在线观看| 日韩欧美一二区| 国产高清一区在线观看| 欧美—级高清免费播放| 国产精品天堂蜜av在线播放 | 欧洲专线二区三区| 久久福利一区二区| 青青青爽久久午夜综合久久午夜| 国产xxxx视频| 亚洲卡通动漫在线| 中文字幕一区二区三区四区欧美| 欧美大胆人体bbbb| 色影视在线观看| 欧洲中文字幕国产精品| 亚洲视频国产| 亚洲第一在线综合在线| 中文欧美日韩| www.四虎在线| 亚洲三级电影网站| 中文字幕无线码一区| 日韩电影中文 亚洲精品乱码| 欧美极品少妇videossex| 国产啪精品视频网站| 精品一区亚洲| 欧美二区在线视频| 成人爽a毛片一区二区免费| 欧美三级黄色大片| 欧美日韩三级视频| yourporn在线观看中文站| 欧美专区中文字幕| 国产精品tv| 岛国大片在线播放| 国产福利91精品一区| 日韩免费av一区| 欧美四级电影在线观看| 免费在线观看污视频| 欧美在线影院在线视频| 九九热播视频在线精品6| 免费一级淫片aaa片毛片a级| 国产精品一区二区果冻传媒| 国产麻豆a毛片| 欧美精品久久久久久久久老牛影院| 国产1区2区3区在线| 国产成人aa精品一区在线播放| 日韩激情啪啪| 亚洲熟妇av日韩熟妇在线| 成人av网站免费| 亚洲男人第一av| 精品一区二区电影| www.com.cn成人| 欧洲精品一区色| 日韩在线一二三区| www久久久久久久| 欧美色涩在线第一页| 婷婷视频在线| 91精品天堂| 亚洲国产免费| 亚洲自拍偷拍一区二区| 色婷婷综合五月| 午夜小视频在线| 91亚洲永久免费精品| 国一区二区在线观看| 成熟妇人a片免费看网站| 婷婷中文字幕综合| 你懂的视频在线免费| 国产精品视频26uuu| 久久激情电影| 国产高清999| 亚洲大型综合色站| 视频二区在线| 国产玖玖精品视频| 欧美伊人久久| 日韩网站在线播放| 欧美日韩久久久一区| 黄色在线观看视频网站| 久久riav二区三区| 蜜桃视频一区二区三区在线观看 | 午夜亚洲国产au精品一区二区| 熟妇人妻中文av无码| 国产精品a久久久久久| 国产精品不卡| 女同性恋一区二区三区| 色久优优欧美色久优优| 国产视频在线播放| 国产区一区二区三区| 男男成人高潮片免费网站| 中国一级片在线观看| 亚洲激情自拍图| 六九午夜精品视频| 欧美久久在线观看| 欧美激情自拍偷拍| 亚洲第一视频在线播放| 国产精品成人一区二区三区吃奶| 欧美 日韩 国产一区二区在线视频| 丰满大乳奶做爰ⅹxx视频| 欧美精品亚洲二区| 日本蜜桃在线观看视频| 一区二区在线不卡| 99re66热这里只有精品3直播| 国产精品欧美激情在线| 98精品国产自产在线观看 | www.亚洲人.com|