别总以为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 阅读(9662) 评论(148) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库