别总以为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的旅程。

 

 

posted on 2012-05-13 17:35  mikelij  阅读(9272)  评论(148编辑  收藏

导航