别总以为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的误解。也有很多讨论,弄得微软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的旅程。

 

 

目录
相关文章
|
开发框架 JavaScript 前端开发
揭秘:如何让你的asp.net页面变身交互魔术师——先施展JavaScript咒语,再引发服务器端魔法!
【8月更文挑战第16天】在ASP.NET开发中,处理客户端与服务器交互时,常需先执行客户端验证再提交数据。传统上使用ASP.NET Button控件直接触发服务器事件,但难以插入客户端逻辑。本文对比此法与改进方案:利用HTML按钮及JavaScript手动控制表单提交。后者通过`onclick`事件调用JavaScript函数`SubmitForm()`来检查输入并决定是否提交,增强了灵活性和用户体验,同时确保了服务器端逻辑的执行。
232 5
|
开发框架 .NET 中间件
七天.NET 8操作SQLite入门到实战 - (2)第七天Blazor班级管理页面编写和接口对接
七天.NET 8操作SQLite入门到实战 - (2)第七天Blazor班级管理页面编写和接口对接
442 7
|
Web App开发 前端开发 Java
基于Spring3 MVC实现基于HTML form表单文件上传
基于Spring3 MVC实现基于HTML form表单文件上传
138 7
基于Spring3 MVC实现基于HTML form表单文件上传
|
开发框架 JSON .NET
ASP.NET Core 标识(Identity)框架系列(三):在 ASP.NET Core Web API 项目中使用标识(Identity)框架进行身份验证
ASP.NET Core 标识(Identity)框架系列(三):在 ASP.NET Core Web API 项目中使用标识(Identity)框架进行身份验证
338 1
|
开发框架 前端开发 .NET
七天.NET 8操作SQLite入门到实战 - (3)第七天Blazor学生管理页面编写和接口对接
七天.NET 8操作SQLite入门到实战 - (3)第七天Blazor学生管理页面编写和接口对接
285 1
|
开发框架 搜索推荐 前端开发
【.NET全栈】ASP.NET开发Web应用——Web部件技术
【.NET全栈】ASP.NET开发Web应用——Web部件技术
|
开发框架 前端开发 安全
ASP.NET MVC 如何使用 Form Authentication?
ASP.NET MVC 如何使用 Form Authentication?
470 0
|
开发框架 .NET 数据库连接
ASP.NET Core 标识(Identity)框架系列(一):如何使用 ASP.NET Core 标识(Identity)框架创建用户和角色?
ASP.NET Core 标识(Identity)框架系列(一):如何使用 ASP.NET Core 标识(Identity)框架创建用户和角色?
370 0
|
Linux C# C++
【.NET Developer】创建ASP.NET Core Blazor项目并打包为Linux镜像发布到Azure应用服务
本文介绍了如何使用VS2019和.NET框架创建一个Blazor应用,并将其部署到Azure应用服务。首先,Blazor是一个使用C#而非JavaScript构建交互式Web UI的框架,支持共享服务器和客户端应用逻辑,以及与Docker和Azure集成。任务包括创建Blazor项目,配置Dockerfile为Linux容器,本地测试,发布到Azure Container Registry (ACR),然后在Azure App Service for Container上部署。在部署过程中,需确保Docker设置正确,开启ACR的Admin访问权限,并监控镜像拉取和容器启动日志。
824 0
|
开发框架 前端开发 JavaScript
JavaScript云LIS系统源码ASP.NET CORE 3.1 MVC + SQLserver + Redis医院实验室信息系统源码 医院云LIS系统源码
实验室信息系统(Laboratory Information System,缩写LIS)是一类用来处理实验室过程信息的软件,云LIS系统围绕临床,云LIS系统将与云HIS系统建立起高度的业务整合,以体现“以病人为中心”的设计理念,优化就诊流程,方便患者就医。
239 0
下一篇
开通oss服务