如何在ASP.NET應用程式中初始化

來源:互聯網
上載者:User

每個程式都需要初始化的過程,用來讀取配置或者設定一些運行環境(變數),對於ASP.NET程式來說,又該在哪裡執行初始化的任務呢?

我想應該絕大多數人都知道在Global.asax中執行初始化的過程,然而有些細節是我們需要關注的。

本文用例

在這篇部落格的範例程式碼中,AppInitializer包含了網站的初始化的實現代碼:

 
  1. public static class AppInitializer  
  2. {  
  3.     public static ConnectionStringSettings MyNorthwindConnectionSetting { get; private set; }  
  4.  
  5.     public static void Init()  
  6.     {  
  7.         // 讀取連接字串。  
  8.         LoadConnectionString();  
  9.  
  10.         // 設定SQLSERVER緩衝依賴通知。  
  11.         SetSqlDependency();  
  12.  
  13.         // 其它的初始化操作。  
  14.         OthersInit();  
  15.     }  
  16.  
  17.     static void LoadConnectionString()  
  18.     {  
  19.         ConnectionStringSettings setting = ConfigurationManager.ConnectionStrings["MyNorthwind"];  
  20.         if( setting == null )  
  21.             throw new ConfigurationException("沒有配置MyNorthwind連接字串。");  
  22.  
  23.         if( string.IsNullOrEmpty(setting.ConnectionString) )  
  24.             throw new ConfigurationException("沒有為MyNorthwind連接字串指定內容。");  
  25.  
  26.         if( string.IsNullOrEmpty(setting.ProviderName) )  
  27.             throw new ConfigurationException("沒有為MyNorthwind連接字串指定ProviderName 。");  
  28.  
  29.         // 儲存讀取到的連接字串,供程式使用。  
  30.         MyNorthwindConnectionSetting = setting;  
  31.     }  
  32.  
  33.     static void SetSqlDependency()  
  34.     {  
  35.         // 判斷SQLSERVER版本是否為 2005以上版本,  
  36.         // 是否開啟Service Broker的檢查代碼就不列出了。  
  37.  
  38.         SqlDependency.Start(MyNorthwindConnectionSetting.ConnectionString);  
  39.     }  
  40.  
  41.     static void OthersInit()  
  42.     {  
  43.         // 其它的初始化操作。  
  44.  
  45.         // 例如:  
  46.         // 1. 載入必要的快取資料。  
  47.         // 2. 檢查上傳目錄是不存在。  
  48.         // 3. ...................  
  49.     }  

這段代碼的意圖很清楚,一定要確保正確的配置了資料庫連接字串,否則以異常的形式報告出來。

樣本程式還有一個頁面,Default.aspx

 
  1. <body> 
  2.     <form id="form1" runat="server"> 
  3.     <div> 
  4.         <h1>User Login</h1> 
  5.     </div> 
  6.  
  7.         <p style="line-height: 150%;"> 
  8.             UserName: <asp:TextBox ID="txtUserName" runat="server" Width="200px" Text="Fish Li"></asp:TextBox><br /> 
  9.             Password: <asp:TextBox ID="txtPassword" runat="server" Width="200px" TextMode="Password"></asp:TextBox><br /> 
  10.             <asp:Button ID="btnLogin" runat="server" Text="登入" OnClick="btnLogin_Click" /> 
  11.         </p> 
  12.     </form> 
  13. </body> 

其實就是一個登入頁面,後台代碼為:

 
  1. protected void btnLogin_Click(object sender, EventArgs e)  
  2. {  
  3.     bool ok = false;  
  4.  
  5.     using( SqlConnection connection  
  6.         = new SqlConnection(AppInitializer.MyNorthwindConnectionSetting.ConnectionString) ) {  
  7.  
  8.         connection.Open();  
  9.  
  10.         // 其它的資料庫操作。  
  11.  
  12.         ok = true;  
  13.     }  
  14.  
  15.     if( ok )  
  16.         Response.Redirect("Default2.aspx");  

你沒有想到的Global.asax怪事!

或許有些人會這樣寫他們的初始化代碼:

 
  1. void Application_Start(object sender, EventArgs e)  
  2. {  
  3.     //在應用程式啟動時啟動並執行代碼  
  4.     try {  
  5.         AppInitializer.Init();  
  6.     }  
  7.     catch( Exception ex ) {  
  8.         LogException(ex);  
  9.           
  10.         // .....................  
  11.     }  
  12. }  

這段代碼有什麼問題呢?

其實問題的線索在於:為什麼要加try....catch語句,是因為知道可能會發生異常嗎?

如果真有異常情況發生,這樣處理後,後續的請求是不是會發生各種想像不到的錯誤?

顯然這裡不能吃掉異常,要不然後面的請求肯定會有問題,因為它們依賴的設定沒有正確的初始化。

好吧,那我去掉 try.....catch語句,這樣總該行了吧:

 
  1. void Application_Start(object sender, EventArgs e)  
  2. {  
  3.     //在應用程式啟動時啟動並執行代碼  
  4.  
  5.     AppInitializer.Init();  
  6. }  

還是看來一下真實的運行情況吧。

噢,抱歉,我還真忘記了配置連接字串,這個異常提示太給力了。

現在就加上連接字串嗎?

別急,想像一下,如果這個網站是一個真實的線上網站,會是什麼情況呢?
答案有二種:

1. 另一個使用者也發起了一次請求。

2. 目前使用者看到錯誤頁面後,重新重新整理了一次當前頁面。

現在我用Opera來扮演第二個瀏覽使用者吧,還是開啟同樣的網址。

太奇怪了,第二個使用者居然能開啟頁面,好吧,讓他登入試試。

結果第二個使用者看到的錯誤情況和第一個使用者完全不同。

如果此時第一個使用者重新整理他的瀏覽器,發現頁面又可以顯示了,然而登入時,會看到與第二個使用者一樣的異常資訊。

這個範例程式碼實在太簡單了,我想維護人員根據NullReferenceException這個線索找下去,很快就能找到答案。如果初始化代碼再複雜一些,比如SetSqlDependency()中出現異常呢,那麼程式仍然能夠正常運行,但是我們期望的緩衝依賴可能就沒有效果了,最終可能會產生效能問題,排查的難度就會大多了。

記得以前做項目時,就遇到過這種情況,當時感到很奇怪,為什麼重新整理一下就沒黃頁了,不過後面的錯誤就很折騰人了,最終也讓我總結了這個教訓。所以我建議:如果在初始化階段出現了異常,乾脆就別讓程式繼續運行了,每個請求都直接顯示黃頁,直到排除故障為止。

如何保證初始化異常一直顯示?

當初始化發生異常時,如何保證初始化異常一直顯示呢?

方法其實並不難,我們需要修改一下代碼:

 
  1. private static Exception s_initException;  
  2.  
  3. void Application_Start(object sender, EventArgs e)  
  4. {  
  5.     try {  
  6.         AppInitializer.Init();  
  7.     }  
  8.     catch( Exception ex ) {  
  9.         // 記下初始化的異常。  
  10.         s_initException = ex;  
  11.     }      
  12. }  
  13.  
  14. protected void Application_BeginRequest(object sender, EventArgs e)  
  15. {  
  16.     // 如果存在初始化異常,就拋出來。  
  17.     // 直到開發人員發現這個異常,並已解決了異常為止。  
  18.     if( s_initException != null )  
  19.         throw s_initException;  
  20. }  

現在不管有多少個使用者來訪問,或者第一個訪問者重新整理瀏覽器多少次,都會看到同樣的異常資訊:

說明:Global.asax的這個問題在IIS7以上版本的整合模式下並不存在。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.