別總以為asp.net mvc比asp.net web form好--web form的頁面也可以體積小巧


最近才看到網上有一種對asp.net web form的誤解。也有很多討論,弄得微軟ScottGu也來澄清。asp.net mvc和web form是並行存在的兩種開發模式。許多人對web form的詬病很多,其中最主要的就是說viewstate,隨便一個web form頁面,其html源碼就體積很大,主要是隱藏字段viewstate體積比較大,至少幾十K,頁面復雜一點,viewstate的大小能上幾兆,這樣大體積的頁面,在瀏覽器和服務器之間傳輸,對網絡帶寬也是一個很大的壓力,所以asp.net webform的性能肯定受很大影響。這其實是一個對asp.net web form的特大誤解。這里提供一個小技巧。可以讓asp.net web form的頁面和asp.net mvc的頁面一樣體積小巧。同時還能享受viewstate帶來的好處。

舉例來說:一個顯示記錄列表的form。如下圖:

 這是一個很簡單的頁面了。其html源代碼是:

 
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>
 
</title>
</head>
<body>
    <form method="post" action="Default.aspx" id="form1">
<div class="aspNetHidden">
<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKLTE5MTIyNjE4Mg9kFgJmD2QWAgIDD2QWAgIBD2QWAgIDDzwrABECAA8WBB4LXyFEYXRhQm91bmRnHgtfIUl0ZW1Db3VudALCA2QMFCsABxYIHgROYW1lBQlBZGRyZXNzSUQeCklzUmVhZE9ubHloHgRUeXBlGSsBHglEYXRhRmllbGQFCUFkZHJlc3NJRBYIHwIFDEFkZHJlc3NMaW5lMR8DaB8EGSsCHwUFDEFkZHJlc3NMaW5lMRYIHwIFDEFkZHJlc3NMaW5lMh8DaB8EGSsCHwUFDEFkZHJlc3NMaW5lMhYIHwIFBENpdHkfA2gfBBkrAh8FBQRDaXR5FggfAgUNU3RhdGVQcm92aW5jZR8DaB8EGSsCHwUFDVN0YXRlUHJvdmluY2UWCB8CBQ1Db3VudHJ5UmVnaW9uHwNoHwQZKwIfBQUNQ291bnRyeVJlZ2lvbhYIHwIFClBvc3RhbENvZGUfA2gfBBkrAh8FBQpQb3N0YWxDb2RlFgJmD2QWDAIBD2QWDmYPDxYCHgRUZXh0BQE5ZGQCAQ8PFgIfBgURODcxMyBZb3NlbWl0ZSBDdC5kZAICDw8WAh8GBQYmbmJzcDtkZAIDDw8WAh8GBQdCb3RoZWxsZGQCBA8PFgIfBgUKV2FzaGluZ3RvbmRkAgUPDxYCHwYFDVVuaXRlZCBTdGF0ZXNkZAIGDw8WAh8GBQU5ODAxMWRkAgIPZBYOZg8PFgIfBgUCMTFkZAIBDw8WAh8GBRMxMzE4IExhc2FsbGUgU3RyZWV0ZGQCAg8PFgIfBgUGJm5ic3A7ZGQCAw8PFgIfBgUHQm90aGVsbGRkAgQPDxYCHwYFCldhc2hpbmd0b25kZAIFDw8WAh8GBQ1Vbml0ZWQgU3RhdGVzZGQCBg8PFgIfBgUFOTgwMTFkZAIDD2QWDmYPDxYCHwYFAjI1ZGQCAQ8PFgIfBgUQOTE3OCBKdW1waW5nIFN0LmRkAgIPDxYCHwYFBiZuYnNwO2RkAgMPDxYCHwYFBkRhbGxhc2RkAgQPDxYCHwYFBVRleGFzZGQCBQ8PFgIfBgUNVW5pdGVkIFN0YXRlc2RkAgYPDxYCHwYFBTc1MjAxZGQCBA9kFg5mDw8WAh8GBQIyOGRkAgEPDxYCHwYFEDkyMjggVmlhIERlbCBTb2xkZAICDw8WAh8GBQYmbmJzcDtkZAIDDw8WAh8GBQdQaG9lbml4ZGQCBA8PFgIfBgUHQXJpem9uYWRkAgUPDxYCHwYFDVVuaXRlZCBTdGF0ZXNkZAIGDw8WAh8GBQU4NTAwNGRkAgUPZBYOZg8PFgIfBgUCMzJkZAIBDw8WAh8GBREyNjkxMCBJbmRlbGEgUm9hZGRkAgIPDxYCHwYFBiZuYnNwO2RkAgMPDxYCHwYFCE1vbnRyZWFsZGQCBA8PFgIfBgUGUXVlYmVjZGQCBQ8PFgIfBgUGQ2FuYWRhZGQCBg8PFgIfBgUHSDFZIDJINWRkAgYPDxYCHgdWaXNpYmxlaGRkGAEFJGN0bDAwJENvbnRlbnRQbGFjZUhvbGRlcjEkZ3JkQWRkcmVzcw88KwAMAQgCWmTq1MHx+5oLH4bMzg2GUy0MyKZQYkR2RY+bxLLJQFR/nQ==" />
</div>
 
<script type="text/javascript"> 
//<![CDATA[
var theForm = document.forms['form1'];
if (!theForm) {
    theForm = document.form1;
}
function __doPostBack(eventTarget, eventArgument) {
    if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
        theForm.__EVENTTARGET.value = eventTarget;
        theForm.__EVENTARGUMENT.value = eventArgument;
        theForm.submit();
    }
}
//]]>
</script>
 
 
    <div>
        
    <span id="ContentPlaceHolder1_Label1">My label</span>
<div>
	<table cellspacing="0" rules="all" border="1" id="ContentPlaceHolder1_grdAddress" style="border-collapse:collapse;">
		<tr>
			<th scope="col">AddressID</th><th scope="col">AddressLine1</th><th scope="col">AddressLine2</th><th scope="col">City</th><th scope="col">StateProvince</th><th scope="col">CountryRegion</th><th scope="col">PostalCode</th>
		</tr><tr>
			<td>9</td><td>8713 Yosemite Ct.</td><td> </td><td>Bothell</td><td>Washington</td><td>United States</td><td>98011</td>
		</tr><tr>
			<td>11</td><td>1318 Lasalle Street</td><td> </td><td>Bothell</td><td>Washington</td><td>United States</td><td>98011</td>
		</tr><tr>
			<td>25</td><td>9178 Jumping St.</td><td> </td><td>Dallas</td><td>Texas</td><td>United States</td><td>75201</td>
		</tr><tr>
			<td>28</td><td>9228 Via Del Sol</td><td> </td><td>Phoenix</td><td>Arizona</td><td>United States</td><td>85004</td>
		</tr><tr>
			<td>32</td><td>26910 Indela Road</td><td> </td><td>Montreal</td><td>Quebec</td><td>Canada</td><td>H1Y 2H5</td>
		</tr><tr>
			<td colspan="7"><table>
				<tr>
					<td><span>1</span></td><td><a href="javascript:__doPostBack('ctl00$ContentPlaceHolder1$grdAddress','Page$2')">2</a></td><td><a href="javascript:__doPostBack('ctl00$ContentPlaceHolder1$grdAddress','Page$3')">3</a></td><td><a href="javascript:__doPostBack('ctl00$ContentPlaceHolder1$grdAddress','Page$4')">4</a></td><td><a href="javascript:__doPostBack('ctl00$ContentPlaceHolder1$grdAddress','Page$5')">5</a></td><td><a href="javascript:__doPostBack('ctl00$ContentPlaceHolder1$grdAddress','Page$6')">6</a></td><td><a href="javascript:__doPostBack('ctl00$ContentPlaceHolder1$grdAddress','Page$7')">7</a></td><td><a href="javascript:__doPostBack('ctl00$ContentPlaceHolder1$grdAddress','Page$8')">8</a></td><td><a href="javascript:__doPostBack('ctl00$ContentPlaceHolder1$grdAddress','Page$9')">9</a></td><td><a href="javascript:__doPostBack('ctl00$ContentPlaceHolder1$grdAddress','Page$10')">10</a></td><td><a href="javascript:__doPostBack('ctl00$ContentPlaceHolder1$grdAddress','Page$11')">...</a></td><td><a href="javascript:__doPostBack('ctl00$ContentPlaceHolder1$grdAddress','Page$Last')">>></a></td>
				</tr>
			</table></td>
		</tr>
	</table>
</div>
<br />
 
    </div>
    </form>
</body>
</html>

可見其隱藏字段viewstate體積較大。對應用程序的性能會有較大影響。 

通過如下方法,可以讓頁面html源代碼體積變小巧。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace EntLibSample
{
    public class BasePage : System.Web.UI.Page
    {
        protected override void SavePageStateToPersistenceMedium(object viewState)
        {
            Session["viewState" + this.Context.Request.FilePath] = viewState;
        }

        protected override object LoadPageStateFromPersistenceMedium()
        {
            if (Session["viewState" + this.Context.Request.FilePath] != null)
            {
                return Session["viewState" + this.Context.Request.FilePath];
            }
            return string.Empty;
        }
    }
}

這個BasePage類繼承了System.Web.UI.Page類。System.Web.UI.Page中的SavePageStateToPersistenceMedium和LoadPageStateFromPersistenceMedium方法是將viewstate的內容發到客戶端瀏覽器中,那么每次向服務器發請求,都需將體積龐大的viewstate字段發回服務器,服務器返回結果時,又將體積龐大的viewstate字段發回來。這給應用程序整體性能帶來了很大沖擊。BasePage類改寫了此兩個方法。將viewstate內容放到session中,用的時候又從session取回來。這樣避免了在網絡上來回傳輸體積龐大的viewstate內容。 

應用程序的所有頁面都繼承此BasePage類。這樣就可以將此方法應用於所有的asp.net web form頁面。

其效果如下:

 
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>
 
</title>
</head>
<body>
    <form method="post" action="Default.aspx" id="form1">
<div class="aspNetHidden">
<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="" />
</div>
 
<script type="text/javascript"> 
//<![CDATA[
var theForm = document.forms['form1'];
if (!theForm) {
    theForm = document.form1;
}
function __doPostBack(eventTarget, eventArgument) {
    if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
        theForm.__EVENTTARGET.value = eventTarget;
        theForm.__EVENTARGUMENT.value = eventArgument;
        theForm.submit();
    }
}
//]]>
</script>
 
 
    <div>
        
    <span id="ContentPlaceHolder1_Label1">My label</span>
<div>
	<table cellspacing="0" rules="all" border="1" id="ContentPlaceHolder1_grdAddress" style="border-collapse:collapse;">
		<tr>
			<th scope="col">AddressID</th><th scope="col">AddressLine1</th><th scope="col">AddressLine2</th><th scope="col">City</th><th scope="col">StateProvince</th><th scope="col">CountryRegion</th><th scope="col">PostalCode</th>
		</tr><tr>
			<td>9</td><td>8713 Yosemite Ct.</td><td> </td><td>Bothell</td><td>Washington</td><td>United States</td><td>98011</td>
		</tr><tr>
			<td>11</td><td>1318 Lasalle Street</td><td> </td><td>Bothell</td><td>Washington</td><td>United States</td><td>98011</td>
		</tr><tr>
			<td>25</td><td>9178 Jumping St.</td><td> </td><td>Dallas</td><td>Texas</td><td>United States</td><td>75201</td>
		</tr><tr>
			<td>28</td><td>9228 Via Del Sol</td><td> </td><td>Phoenix</td><td>Arizona</td><td>United States</td><td>85004</td>
		</tr><tr>
			<td>32</td><td>26910 Indela Road</td><td> </td><td>Montreal</td><td>Quebec</td><td>Canada</td><td>H1Y 2H5</td>
		</tr><tr>
			<td colspan="7"><table>
				<tr>
					<td><span>1</span></td><td><a href="javascript:__doPostBack('ctl00$ContentPlaceHolder1$grdAddress','Page$2')">2</a></td><td><a href="javascript:__doPostBack('ctl00$ContentPlaceHolder1$grdAddress','Page$3')">3</a></td><td><a href="javascript:__doPostBack('ctl00$ContentPlaceHolder1$grdAddress','Page$4')">4</a></td><td><a href="javascript:__doPostBack('ctl00$ContentPlaceHolder1$grdAddress','Page$5')">5</a></td><td><a href="javascript:__doPostBack('ctl00$ContentPlaceHolder1$grdAddress','Page$6')">6</a></td><td><a href="javascript:__doPostBack('ctl00$ContentPlaceHolder1$grdAddress','Page$7')">7</a></td><td><a href="javascript:__doPostBack('ctl00$ContentPlaceHolder1$grdAddress','Page$8')">8</a></td><td><a href="javascript:__doPostBack('ctl00$ContentPlaceHolder1$grdAddress','Page$9')">9</a></td><td><a href="javascript:__doPostBack('ctl00$ContentPlaceHolder1$grdAddress','Page$10')">10</a></td><td><a href="javascript:__doPostBack('ctl00$ContentPlaceHolder1$grdAddress','Page$11')">...</a></td><td><a href="javascript:__doPostBack('ctl00$ContentPlaceHolder1$grdAddress','Page$Last')">>></a></td>
				</tr>
			</table></td>
		</tr>
	</table>
</div>
<br />
 
    </div>
    </form>
</body>
</html>

 可見viewstate字段的內容完全沒有了。這樣html源代碼的整體體積就小了很多。這對應用程序的性能提高是很大好處的。曾經只有asp.net mvc才有的體積小頁面,現在asp.net web form也可以做到了。同時asp.net web form還有開發效率相對較高,還可以利用viewstate帶來的好處,有了這些綜合考慮,大家應該會重拾對asp.net web form的信心,繼續在asp.net web form的旅程。

 

 


免責聲明!

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



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