ASP.NET編程中你也應該知道的那些事


首先說一下我的上一篇文章:這些年、我收集的JQuery代碼,由於剛接觸Live Writer不久,不是很熟悉,看到園友們反饋的錯誤,不想誤導大家,就在瀏覽器中直接修改了,可能是由於代碼段是VSPaste粘貼的緣故,保存后導致排版亂掉了。我是一個追求完美的人,不願意看到那樣參差不齊的代碼,更不願意讓園友們看到。於是就決定刪除重新發布。現在已經重新發布了,可能還是會有寫問題是我沒有察覺到的,歡迎大家指出。。。還有我發現博客園的隨筆不能編輯權限,比如發布了一篇隨筆,但是后來我不想讓別人看到這篇隨筆了,怎么辦?現在好像只能刪除,要是能設置不公開就好了,好像博客園現在還沒這功能吧?還是我沒發現?希望“園長”可以考慮一下眨眼,好了 不說廢話了進入今天的主題。

 

1、跟蹤頁面執行

設置斷點是頁面調試過程中的常用手段,除此之外,還可以通過查看頁面的跟蹤信息進行錯誤排查以及性能優化。

asp.net中啟用頁面跟蹤非常方便,只需在Page指令中加入Trace="True"屬性即可:

<%@ Page Language="C#" Trace="true" %>
 跟蹤信息可以分為兩類:
a.頁面執行詳細情況
其中主要包括頁面生命周期中各事件列表、控件樹列表(可以查看每個控件的HTML字節數以及ViewState字節數)、Session狀態、Application狀態、Cookie集合、QueryString集合、服務器變量等信息。
 
b.自定義跟蹤信息
通過在頁面代碼中調用Trace.Write()或Trace.Warn()方法便可將指定內容寫入跟蹤信息中的"Trace Information"節。就算頁面發生了錯誤,跟蹤信息還是會顯示出來,並且在發布應用程序時無需刪除相關的跟蹤代碼,只需從Page指令中移除Trace屬性即可。

2、在服務器端控件中添加客戶端屬性

我們有時會向服務器端控件中添加一些特殊的屬性,這類屬性不需要服務器端的處理,只需簡單的發送至客戶端即可,我們不妨稱其為客戶端屬性,例如HTML屬性或自定義屬性(可能用於實現某種特定的JavaScript功能)。可以通過以下幾種方法達到這個目的

 

a.直接向控件添加客戶端屬性

 <asp:Button ID="MyButton" Text="ClickMe" onmouseover="this.style.cursor='pointer'" 
 runat="server" />
其中的onmouseover是客戶端屬性,注意,編譯器是允許這種寫法的,但會顯示警告。使用是正常的。
 
b.調用內置方法
可以通過調用WebControl.Attributes.Add()方法為控件添加客戶端屬性,如下所示
 MyButton.Attributes.Add("onmouseover", "this.style.cursor='pointer'");
 
c.使用OnClientClick
asp.net 2.0以后為按鈕控件(包括Button、LinkButton、ImageButton控件)提供了OnClientClick屬性,可以這樣寫
 MyButton.OnClientClick = "alert('Hello!')";
3、表單數據的服務器端驗證

將數據驗證任務從服務器端遷移到客戶端的過程促使了JavaScript的產生,這也是我們沿用至今的一種方式。但只有在保證客戶端JavaScript正常運行的前提下,這種方式才能發揮其作用。不幸的是,總有一些例外,比如瀏覽器不支持JavaScript,或者用戶刻意關閉了瀏覽器的JavaScript功能,這就導致了第一重防護失效。比較保險的做法是加入第二重防護,即對用戶提交的數據進行服務器端驗證,但這無疑將增加開發者的工作量。

asp.net 2.0提供了一系列表單數據驗證控件,可以非常輕松的完成客戶端及服務器端的雙重數據驗證任務。但要使服務器端驗證功能發揮作用,還需要用到Page.IsValid屬性,請看下面的例子

 <form id="MyForm" runat="server"> <div> Username<asp:TextBox ID="txtName" runat="server"></asp:TextBox> <asp:RequiredFieldValidator ID="RequiredFieldValidator1" ControlToValidate="txtName" 
 ErrorMessage="input ur name" Display="Dynamic" runat="server">
 </asp:RequiredFieldValidator> </div> <div> <asp:Button ID="btnSubmit" Text="submit" runat="server" /> </div> </form>
這是一個HTML片段,其中有一個RequiredFieldValidator控件用於檢查是否已填寫姓名。下面是點擊按鈕時執行的服務器端代碼:
 protected void btnSubmit_Click(object sender, EventArgs e) { if (Page.IsValid) //注意:不要遺漏對Page.IsValid屬性的判斷 { Response.Write("你的名字是:" + txtName.Text); } }
其中,要特別注意對Page.IsValid屬性的判斷,只有頁面中所有驗證控件對數據的驗證都成功時,Page.IsValid屬性才為True,這代表提交的數據為有效數據,可以進入下一步操作。
4、跳過表單驗證

在某些情況下,我們需要跳過表單中所有控件的驗證,然而在另外一些情況下,我們卻希望有選擇的觸發表單中某些控件的驗證功能。分別來看看這兩種情況:

 

a.跳過所有驗證

假設有個表單,其中除了各種數據錄入控件外還有兩個按鈕,一個是提交按鈕,另一個是取消按鈕,同時表單中還有一些數據驗證控件。我們希望當點擊取消按鈕的時候無需驗證表單中數據的有效性,而是直接將頁面提交至服務器並將其重定向到某個指定頁面。

要實現這個功能,可以利用按鈕控件(包括Button、LinkButton、ImageButton控件)的CausesValidation屬性,將該屬性設為false即可跳過表單中的所有驗證。

 

b.觸發某些驗證

假設有個表單,被划分成兩個功能區,一個用於用戶登錄,另一個用於用戶注冊,我們希望當點擊登錄按鈕時只觸發登錄區的數據驗證,當點擊注冊按鈕時只觸發注冊區的數據驗證。

解決辦法是將相關的數據驗證控件和數據提交控件(按鈕控件)加入同一個驗證組,這一點是通過將各相關控件的ValidationGroup屬性設為相同的值來實現的。

5、保持滾動條位置

假設有個頁面,其中以列表形式顯示了一些數據記錄,每次編輯其中的記錄時都需要向服務器提交頁面,為了提供良好的用戶體驗,我們希望每次編輯一條記錄並保存后,滾動條位置都能保持不變。傳統的做法是每次提交頁面時將當前滾動條所在位置信息按某種方式(Hidden字段或QueryString)傳給服務器端,當頁面返回客戶端時,由服務器端根據傳入的位置信息以JavaScript形式重新設置滾動條位置。

如果通過asp.net來實現這一功能將變得非常簡單,只需在Page指令中加入MaintainScrollPositionOnPostback="true"屬性即可:

<%@ Page Language="C#" MaintainScrollPositionOnPostback="true">%>
6、禁用不必要的ViewState

在asp.net的運行機制中,ViewState起着重要的作用。ViewState經過編碼后存入表單Hidden字段,每當頁面回傳至服務器時再進行解碼。因此,ViewState的使用會帶來兩個問題:帶寬的占用以及計算資源的消耗。好在不是所有控件都需要啟用ViewState,我們完全可以禁用不必要的ViewState。

ViewState默認是開啟的,需要手動關閉:

 

a.禁用頁面ViewState

在Page指令中加入EnableViewState="false"屬性即可:

<%@ Page Language="C#" EnableViewState="false">%>
加入這個屬性后,整個頁面以及其中的所有控件都將無法使用ViewState,因此需謹慎使用
 

b.禁用控件ViewState

這是推薦的方式,將控件的EnableViewState屬性設為False即可禁用其ViewState,這里有個簡單的竅門:

如果某個控件的狀態不能由操作者改變,則可以禁用其ViewState。最典型的莫過於Label控件了,只能顯示信息,無法操作。

但TextBox、DorpDownList等控件的狀態是可以改變的(通過輸入、選擇等操作),因此保留他們的ViewState還是有用的。

 7、一些提高運行速度的小技巧

1)避免使用ArrayList,因為對象要轉化為System.Object加入ArrayList,取出時又要轉化為想要的類型,設計到大量的裝箱拆箱過程,推薦使用自定義集合取代ArrayList,.net還在System.Collection.Specialized命名空間下為string提供了一個強類型的集合類StringCollection

2)用Hashtable 取代其他字典類型,如:StringDictionary, NameValueCollection, HybridCollection。

3)經常為字符串聲明常量來封裝他們

  //避免 MyClass obj = new MyClass(); obj.name = "name";  //推薦 const string c_name = "name"; MyClass obj = new MyClass(); obj.name = c_name;

4)使用String.Compare取代將兩個字符串轉化為uppercase或lowercase再來比較他們

 const string C_VALUE = "COMPARE"; if (String.Compare(sVariable, C_VALUE, true) == 0) Console.Write("SAME");
5)避免使用+操作符來連接字符串,而使用StringBuilder來連接
 
  //避免 String sXML = "<parent>"; sXML += "<child>"; sXML += "Data"; sXML += "</child>"; sXML += "</parent>";  //推薦 StringBuilder sbXML = new StringBuilder(); sbXML.Append("<parent>"); sbXML.Append("<child>"); sbXML.Append("Data"); sbXML.Append("</child>"); sbXML.Append("</parent>");
6)對於只讀xml文檔,用XPathDocument取代XMLDocumentt
  //避免 XmlDocument xmld = new XmlDocument(); xmld.LoadXml(sXML); txtName.Text = xmld.SelectSingleNode("/packet/child").InnerText;  //推薦 XPathDocument xmldContext = new XPathDocument(new StringReader(oContext.Value)); XPathNavigator xnav = xmldContext.CreateNavigator(); XPathNodeIterator xpNodeIter = xnav.Select("packet/child"); iCount = xpNodeIter.Count; xpNodeIter = xnav.SelectDescendants(XPathNodeType.Element, false); while (xpNodeIter.MoveNext()) sCurrValues += xpNodeIter.Current.Value + "~";
7)避免在循環體類聲明並初始化對象,而應該在循環體外聲明,在循環體類初始化!
  //避免 for (int i = 0; i < 10; i++) MyClass objSC = new MyClass();  //推薦 MyClass objSC = null; for (int i = 0; i < 10; i++) objSC = new MyClass();
我覺得應盡量少用服務器端控件,一般情況下用服務器端(runat=server)控件會使性能損失30-50%左右(沒有測試過,數據來源於網絡吐舌鬼臉
文章的內容很淺,對於園子里的大牛們可能沒有什么幫助,但是我覺得像我們這樣的小菜鳥還是獲益良多的。資源整理自網絡。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM