Webform Application传值 ViewState

Application:所有的会话共享一个Application空间,任何一个人改变Application的内容,其他人都会发现被改变了。Application中的内容不会被自动释放

存放位置:服务端
所有的访问用户都是访问的同一个变量

(1)用Application存值:Application["key名"] = 值; 值,不只是个字符串,可以是对象。

        string s = TextBox1.Text;
        Application["aaa"] = s;

(2)用Application取值:类型 变量名 = (强制转换的类型名)Application["key名"]

protected void Page_Load(object sender, EventArgs e)
    {
        if(Application["aaa"]!=null)
        {
            Label1.Text=(string)Application["aaa"];
           // Label1.Text = Application["aaa"].ToString();
        }
    }

(3)判断Application中是否存有某个值
if(Application[“key名”] == null)
{

}
(4)释放Application:Application["key名"] = null;

案例:每次访问页面都会累加访问次数

 protected void Page_Load(object sender, EventArgs e)
    {
        if (Application["count"] == null)
        {
            Application["count"] = 0;
        }
        Application["count"] = (int)Application["count"] + 1;

        Label1.Text = Application["count"].ToString();
    }

隐藏的状态—ViewState探秘

1.1 从Http的无状态说起

  Http是一个无状态协议,同一个会话的连续两个请求互相不了解,它们由最新实例化的环境进行解析,除了应用本身可能已经存储在全局对象中的所有信息外,该环境不保存与会话有关的任何信息。另外,因为,浏览器和服务器之间是通过Socket进行通信,Http请求通常请求完毕就会关闭Socket连接,因此Http协议不会保持连接。如果保持连接会降低客户端并发处理请求数,不保持连接又会降低处理速度(建立连接所需的时间会长一点);

PS:这里我们可以这样来理解:假如我们去一个大型商场购物购买某个产品,第一次去的时候是A销售员接待了我们,带领我们来到XX产品的柜台并为我们推荐了XX产品;等我们回去使用XX产品后,觉得XX产品真心不错。第二次我们又去,但是这次却找不到上次那个A销售员了,相反商场分配了另一个B销售员来接待我们,他不知道我们上次选择了XX产品,相反它却一个劲地向我们推荐YY产品并把我们带向YY产品的柜台;这个时候,我们一般会说:我擦,把上次那个妹子给我叫来!

  基于Http协议的无状态特性,我们在ASP.Net的开发中也会经常碰到这种情况:用户上一次提交的东西,下次再提交时服务器就不记得了。很多时候,我们感到很不解?后来,我们发现原来每一次的请求服务器都开启了不同的线程来处理,也就是说每次都会new一个XXX.aspx.cs中的类对象实例来进行处理(上一次new出来为我们处理的page对象也许早就被服务器销毁了)。比如,我们在xxx.aspx.cs代码中写入了一个int类型的number成员(初始为0),每次请求我们都想让这个number自增一下,然后重新返回给浏览器。但就是这么一个简单的梦想,我们却无法轻易的实现。

 那么,到底怎么来破呢?大神们已经为我们想好了策略,我们可以使用隐藏域字段、Cookie、Session等来保存状态。而伟大的Microsoft还在ASP.Net中帮我们封装了ViewState,以至于我们在WebForm中进行PostBack操作时,都感觉不到服务器是无状态的。

1.2 青春四处绽放—无处不在的ViewState

  (1)类似于Dictionary的一种数据结构

  如果你曾经使用过Dictionary或者Session的话,那么你应该了解这种Key/Value的数据结构。这里并没有什么高深的理论,ViewState通过String类型的数据作为索引。ViewState对应项中的值可以存储任何类型的值(参数是Object类型),实施上任何类型的值存储到ViewState中都会被装箱为Object类型。

  例如,这里我们可以改写上面那个按钮事件中的代码:

 

  这里,我们借助ViewState存储了age的状态值,第一次来我给你返回1,后面再来我就加1再返回给你。于是,在上一节我们所提到的那个问题(无法记住上次的number值,每次都返回1)就解决了。

PS:ViewState不能存储所有的数据类型,仅支持以下的这几种:
String、Integer、Boolean、Array、ArrayList、Hashtable以及一些自定义类型

  我们都知道,Dictionary和Session都是存储在服务器端的。那么,我们不禁要问,既然我们在服务器端给ViewState增加了一个Key/Value对,并返回给浏览器端,ViewState又是存储在什么位置的呢?

  (2)大隐隐于市的“页面级”隐藏字段

  跟Session和Dictionary的存储位置不同,ViewState的作用域是页面,也就是说ViewState是存储在浏览器的页面之中的(这里相比Session等,耗费的服务器资源较少,也算是ViewState的优点之一吧),当你关闭某个aspx文件后,那么属于这个aspx的ViewState也就不存在了。或许,这么说来,我们还不是很了解,现在我们来实地看看。

  ①首先,如果页面上有一个runat="server"的form,当用户请求这个页面时,服务器会自动添加一个_ViewState的隐藏域返回给浏览器。但是,我们发现这个ViewState的value看起来像一串乱码?这是为什么呢?这是因为服务器在向浏览器返回html之前,对ViewState中的内容进行了Base64的加密编码

  ②其次,当用户点击页面中的某个按钮提交表单时,浏览器会将这个_VIEWSTATE的隐藏域也一起提交到服务端;服务器端在解析请求时,会将浏览器提交过来的ViewState进行反序列化后填充到ViewState属性中(比如下图中,我们可以通过一个软件将_VIEWSTATE解码得到一个如下图所示的树形结构);再根据业务处理需要,从这个属性中根据索引找到具体的Value值并对其进行操作;操作完成后,再将ViewState进行Base64编码再次返回给浏览器端;

  ③因此,我们可以得出一个结论:VIEWSTATE适用于同一个页面在不关闭的情况下多次与服务器交互(PostBack)。这里我们也可以通过下图来温习一下ViewState的流程,ViewState存放着“事故现场”,下次可以方便地“还原现场”,将无状态的Http模拟成了有状态的,也让广大的初学者了解不到无状态的这个特性。

1.3 喜欢就会放肆—又爱又恨的ViewState!

  事实上,除了我们手动在服务器端向ViewState属性中添加的K/V对数据,我们在aspx.cs代码中为某些服务器控件设置的值(例如:为Repeater设置DataSource中存入的数据集、为Label所设置的Text内容等,但不包括:TextBox、CheckBox、CheckboxList、RadioButtonList)都存入了ViewState中。这样做的话,我们下次再向服务器提交请求时,现有表单中所有的服务器控件状态都会记录在ViewState中提交到服务器,在服务器端可以方便地对这些服务器控件进行有状态的操作并返回,这无疑是让我们欢喜的,因为方便了我们的开发过程,提高了我们的开发效率;

  但有人说:“喜欢就会放肆”,ViewState让人又爱又恨啊。例如,在我们使用Repeater的过程中,WebForm会自动将DataSource(数据源,你可以理解为一个集合)存储到ViewState中并返回给浏览器。可以参考下面的例子来实地理解一下:

  ①含有Repeater的aspx页面:

 

  ②后台代码模拟从数据库中取得数据集合并绑定到Repeater中:

 

  编译生成后,通过查看此页面的html代码,可以明显看到一长串的_VIEWSTATE隐藏域。将此_VIEWSTATE复制到ViewStateDecoder中进行反编码,可以发现它确实存储了Repeater中的数据集合。这里我们不禁要问:展示数据既然已经渲染成了html,为何还要存储在ViewState隐藏域中?如果我们的数据集合是一百行、一千行数据的话,那ViewState隐藏域岂不很大(100k?200k?)?但不幸的是,这是ViewState的设计机制,要想依靠它来保持状态,它就会将服务器控件的状态包括数据集合都存储到其中,在浏览器和服务器之间来回传递保持状态。

  这里就涉及到网站的性能问题的探讨了:由于ViewState存储在页本身,因此如果存储较大的值,用户请求显示页面的速度会减慢(这对于互联网系统来说,就是一个噩梦。你会选择一个1秒内响应的网站浏览还是5秒内响应的网站?)。又因为ViewState会随同Form表单一同回传给服务器,如果ViewState很大的话,Http报文也会很大,网站流量消耗也会增大。

  那么,有没有一种方法可以让ViewState克制一下呢?别急,请看下面的介绍。

1.4 但爱就是克制—禁用还是不禁用ViewState?

  刚刚说到,因为ViewState会一定程度上影响性能,所以我们可以在不需要的时候禁用 ViewState。默认情况下 ViewState 将被启用,并且是由每个控件(而非页面开发人员)来决定存储在 ViewState 中的内容。有时,这一信息对应用程序并没有什么用处(例如上面提到的Repeater的数据集合,已经渲染生成了html显示,还存储了一份副本在ViewState里边)。尽管也没什么害处,但却会明显增加发送到浏览器的页面的大小。因此如果不需要用ViewState,最好还是将它关闭,特别是当 ViewState 很大的时候。当然,ViewState帮我们实现了某些服务器控件状态保持,因此在非必需的情况下,还是可以适度使用的,特别是在开发企业内部信息系统的场景。

  那么,怎样来禁用ViewState呢?禁用ViewState又有什么策略呢?下面我们一一来探讨。

  ①页面级禁用ViewState:在aspx的首部的Page指令集中添加EnableViewState="false",该页面中所有控件的状态都不会存入ViewState的,页面一下就会清爽许多;

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="RepeaterViewState.aspx.cs"
    Inherits="WebFormDemo.RepeaterViewState" EnableViewState="false" %>

  禁用后,再次查看生成的html代码,我们会发现:咦,_VIEWSTATE还在那儿,但是明显比先前的体积小了不少

  再将这个瘦身后的_VIEWSTATE复制到ViewStateDecoder中进行反编码查看,我们会发现,只保存了一个最基本的信息,Repeater的那些数据集合没有存入进去了。

PS:为什么禁用ViewState之后,页面源代码中仍然有_VIEWSTATE的隐藏域

这是因为就算禁用了viewstate,aspx页面中还是会有一个服务器控件在那里使用,这就是<form runat="server">。这时,如果你将form去掉runat="server",将其变为普通html标签,那么页面就干净了,从此_VIEWSTATE这个隐藏域彻底消失在你的页面中。

  ②控件级禁用ViewState:在某些场景中,我们只希望禁用某个控件(例如Repater)的ViewState,其他控件仍然通过ViewState保持状态。这时,我们可以给指定的控件设置一个属性EnableViewState="false"即可;

<asp:Repeater ID="repeaterProducts" runat="server" EnableViewState="false">
</asp:Repeater>

  ③全局级禁用ViewState:园子里的大神老赵(Jeffrey Zhao)曾经说过,“我如果新建一个WebForm项目,做的第一件事情就是去Web.config中将enableViewState设置为false从而将ViewState全局关闭”。那么,我们如果希望将网站中所有页面的ViewState都禁用,总不可能去一个一个页面得修改Page指令吧?ASP.Net为我们提供了一个配置,我们只需要在Web.config的system.web中增加一句配置即可:

<pages enableViewState="false" />

PS:开发中也可以采用大神老赵的做法,先禁用,再选择性启用,毕竟没有非要ViewState才能干成的事儿!

  ④真正的禁用ViewState:刚刚我们的三种方法实践后,在页面还是出现_VIEWSTATE的隐藏域,尽管它保留了最基本的信息。那么,我们可能会问?怎样才能彻底地真正地禁用ViewState,根本就别给我生成_VIEWSTATE的隐藏域。答案是有的,将<form runat="server"/>的runat="server"去掉,就不会出现了,但那样又会偏离WebForm的开发模式,大部分的服务器控件都无法正常使用,开发效率又会有所损失。

  综上所述,在实际开发中应该权衡利弊,特殊情况特殊分析(到底这个场景该不该禁用ViewState),选择是否禁用ViewState,采用何种方式禁用ViewState。对于ViewState的探秘本篇就到此为止,由于我本人理解的也不是很深刻,所以希望各位园友如果有理解,可以回复出来大家探讨共同进步。

时间: 2024-10-11 08:04:00

Webform Application传值 ViewState的相关文章

【2017-05-22】WebForm内置对象:Application和ViewState、Repeater的Command用法

一.内置对象 1.Application 存贮在服务器端,占用服务器内存生命周期:永久 所有人访问的都是这一个对象 传值:传的是object类型可以传对象. string s =TextBox1.Text; Application["aaa"]=s; 取值: if(Application["aaa"]!=null) { Label1.Text=Application["aaa"].toString(); } 2.ViewState ViewSta

内置对象session ,cookic,Application,ViewState

一.内置对象 (一)Response - 响应请求对象1.定义:Response对象用于动态响应客户端请示,控制发送给用户的信息,并将动态生成响应.Response对象只提供了一个数据集合cookie,它用于在客户端写入cookie值.若指定的cookie不存在,则创建它.若存在,则将自动进行更新.结果返回给客户端浏览器.2.方法(1)Redirect用法:Response.Redirect("url")作用是在服务器端重定向于另一个网页(2)Write功能:向客户端发送浏览器能够处理

内置对象Application、ViewState

Application: 全局公共变量组 存放位置:服务器 特点:所有访问用户都是访问同一个变量,但只要服务器不停机,变量一直存在于服务器的内存中,不要使用循环大量的创建Application对象,可能会造 成服务器崩溃. 生命周期:永久,只要服务器不停机 使用方法:与Session一样 ViewState: 用于记录页面的一些状态,就像人的病例,比如当执行提交后,网页可以保留一些已经输入的文本框而非清空 webform中微软已经给我们做好了这个对象,自带此功能.

内置对象(Session、Application、ViewState)

内置对象:为了跨页面传值和状态保持.→HTTP的无状态性 [4.]Session:每一台电脑访问服务器,都会是独立的一套session,key值都一样,但是内容都是不一样的 以上所有内容,都跟cookies一样 不一样:1.Session的保存位置是保存在服务器上2.Session没有持久的,它的保存周期就是20分钟 重点:Session不要滥用,也不要不用,滥用可能会造成服务器内容溢出,不用会造成资源浪费,因为内存中的数据提取及交互是最快的 赋值:Session["key"] = 值

webform 页面传值的方法总结

ASP.NET页面之间传递值的几种方式 页面传值是学习asp.net初期都会面临的一个问题,总的来说有页面传值.存储对象传值.ajax.类.model.表单等.但是一般来说,常用的较简单有QueryString,Session,Cookies,Application,Server.Transfer. 一.QueryString QueryString是一种非常简单的传值方式,他可以将传送的值显示在浏览器的地址栏中.如果是传递一个或多个安全性要求不高或是结构简单的数值时,可以使用这个方法.但是对于

application、viewstate、纯HTML提交方式

Application - 全局公共变量组 存放位置:服务端 所有的访问用户都是访问的同一个变量 声明周期:永久 用法同session类似 viewstate-病例 因为http的无状态性,需要记录上一个页面的状态,因而需要一个viewstate记录上一个页面的状态,然后返回成相应的内容 纯HTML提交: HTML界面: 要写action与method: <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"

webform页面传值和删除修改

一.webform跨页面传值1.内置对象地址栏数据拼接 QueryString 优点:简单好用:速度快:不消耗服务器内存. 缺点:只能传字符串:保密性差(调转页面后在地址栏显示):长度有限.响应请求对象 Response获取请求对象 Request(1)跳转页面 Response.Redirect(path);//重定向,可以跳转任何网页 Rerver.Trandfer(path);//跳转后地址栏的网址不改变,只能跳转该网站根目录下的网站 Respone.Write("<script&g

WebForm 页面传值

一.使用Querystring Querystring是一种非常简单的传值方式,其缺点就是会把要传送的值显示在浏览器的地址栏中,并且在此方法中不能够传递对象.如果你想传递一个安全性不是那么太重要或者是一个简单的数值时,用此方法最好不过了.下面通过一个小例子来完成传值工作,步骤如下: 1.创建一个web form 2.在新建的web form中放置一个button1,在放置两个TextBox1,TextBox2 3.为button按钮创建click事件 代码如下:private void butt

C# webform 页面传值

1.aspx 间 传值: Session["name"] = ds1.Tables[0].Rows[0]["name"]; 接收值:     string tempname = Session["name"].ToString();                lblname.Text = tempname; 2.rdlc与aspx间 传值:  ="javascript:location.href='image.aspx?fj=&qu