zoukankan      html  css  js  c++  java
  • 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类型。

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

     View Code

       这里,我们借助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页面:

     View Code

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

     View Code

      编译生成后,通过查看此页面的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的探秘本篇就到此为止,由于我本人理解的也不是很深刻,所以希望各位园友如果有理解,可以回复出来大家探讨共同进步。

  • 相关阅读:
    SAP S/4HANA extensibility扩展原理介绍
    SAP CRM系统订单模型的设计与实现
    使用nodejs代码在SAP C4C里创建Individual customer
    SAP Cloud for Customer Account和individual customer的区别
    Let the Balloon Rise map一个数组
    How Many Tables 简单并查集
    Heap Operations 优先队列
    Arpa’s obvious problem and Mehrdad’s terrible solution 思维
    Passing the Message 单调栈两次
    The Suspects 并查集
  • 原文地址:https://www.cnblogs.com/baimangguo/p/6255565.html
Copyright © 2011-2022 走看看