您的位置:首页 > 编程语言 > ASP

如何在asp.net中保存用户状态

2005-02-16 14:44 477 查看
ASP.NET为保持用户请求之间的数据提供了多种不同的途径。你可以使用Application对象、cookie、hidden fields、Sessions或Cache对象,以及它们的大量的方法。在ASP.NET中,有几种保持用户请求间数据的途径--实际上太多了,使没有经验的开发者对在哪个特定的环境下使用哪个对象很困惑。为了回答这个问题,需要考虑下面三个条件:
1.谁需要数据?

2.数据需要保持多长时间?

3.数据集有多大?

  通过回答这些问题,你能决定哪个对象为保持ASP.NET应用程序请求间数据提供了最佳的解决方案。下面列出了不同的状态管理对象并描述了什么时候使用它们。ASP.NET中添加了四个新的对象:Cache、Context、ViewState和Web.Config文件。ASP.NET也支持传统的ASP对象,包括Application、 Cookie、有隐藏字段的 Form Post 、 QueryString和Sessions。

保持方法谁需要数据保持多长时间数据量大小
Application所有用户整个应用程序生命期任意大小
Cookie一个用户可以很短,如果用户不删除也可以很长小的、简单数据
Form Post一个用户到下一次请求(可以跨越多个请求重复使用)任意大小
QueryString一个或一组用户 到下一次请求(可以跨越多个请求重复使用)小的、简单数据
Sessions一个用户用户活动时一直保持+一段时间(一般20分钟)可以是任何大小,但是因为用户有单独的Sessions 存储,所有它应该最小。
Cache 所有用户或某些用户根据需要可大可小、可简单可复杂
Context一个用户 一个请求可以保持大对象,但是一般不这样使用
ViewState 一个用户一个Web窗体最小
Config file所有用户 直到配置文件被更新 可以保持大量数据,通常组织小的字符串和XML结构
ASP.NET中的数据容器对象

Application

  让我们通过回答上面的状态问题判定条件来说明该对象。谁需要数据?所有的用户需要访问它。需要保持数据多长时间?永久保持,或在应用程序生存期中保持。数据多大?可以是任何大小--在任何给定的时刻只有数据的一个副本存在。

  在传统ASP中,Application对象提供了一个保存频繁使用但很少改变的数据片的位置,例如菜单内容和参考数据。尽管在ASP.NET 中Application依然作为数据容器存在,但是有其它一些更适合以前保存在传统ASP应用程序的Application集合中的数据的对象。

  在传统的ASP中,如果被保存的数据在应用程序的生存期中根本不会改变(或很少改变,例如只读数据和大多数情况下是读操作的数据),Application对象是理想的选择。连接字符串就是保存在Application变量中的一个最普通的数据片,但是在ASP.NET中类似的配置数据最好保存在Web.config文件中。如果使用Application对象一个需要考虑的问题是任何写操作要么在Application_OnStart事件(global.asax)中,要么在Application.Lock部分中完成。尽管使用Application.Lock来确保写操作正确地执行是必要的,但是它串行化了对Application对象的请求,而这对于应用程序来说是个严重的性能瓶颈。

Application.aspx.cs

private void btnSubmit_Click(object sender, System.EventArgs e)

{

if(IsValid)

{

Application.Lock();

Application[txtName.Text] = txtValue.Text;

Application.UnLock();

}

}

Cookies

  当特定的用户需要特定的数据片,并且需要把数据在某个可变的时段中保持的时候,cookie就非常方便。它的生命周期可能与浏览器窗体的一样短,也可以长达数月、数年。cookie可以小到只有几个字节的数据,因为它们在每个浏览器请求中传递,它们的内容需要尽可能的小。

  Cookie提供了一条灵活的、强大的维护用户请求间数据的途径,这就是为什么Internet上大多数动态站点使用它们的原因。因为cookie可以存储的数据量很受限制,最好只在cookie中保存键字段,其它的数据保存在数据库或其它的服务器端数据容器中。但是由于不是所有的浏览器都支持cookie,并且它可以被用户禁止或删除,因此它们也不能用于保存关键数据。你应该很好地处理用户的cookie被删除的情况。最后,cookie作为简单的明文文本保存在用户的计算机中,因此在它里面不能保存敏感的、未加密的数据。

Cookies.aspx.cs

//使用HttpCookie类是指cookie的值和/或子值

HttpCookie cookie;

if(Request.Cookies[txtName.Text] == null)

cookie = new HttpCookie(txtName.Text, txtValue.Text);

else

cookie = Request.Cookies[txtName.Text];

if(txtSubValueName.Text.Length > 0)

cookie.Values.Add(txtSubValueName.Text, txtSubValueValue.Text);

cookie.Expires = System.DateTime.Now.AddDays(1); // tomorrow

Response.AppendCookie(cookie);

//检索cookie的值

if(!Request.Cookies[txtName.Text].HasKeys)

lblResult.Text = "The value of the <b>" + txtName.Text + "</b>

cookie is <b>" + Request.Cookies[txtName.Text].Value.ToString() +

"</b>";

else

{

lblResult.Text = "The value of the <b>" + txtName.Text + "</b>

cookie is <b>" + Request.Cookies[txtName.Text].Value.ToString() +

"</b>, with subvalues:<br>";

foreach(string key in Request.Cookies[txtName.Text].Values.Keys)

{

lblResult.Text += "[" + key + " = " +

Request.Cookies[txtName.Text].Values[key].ToString() + "]<br>";

}

}

删除Cookie

// 把的值设置为空并把终止时间设置为过去某个时刻

Response.Cookies[txtName.Text].Value = null;

Response.Cookies[txtName.Text].Expires =

System.DateTime.Now.AddMonths(-1); //上个月

Form Post / 隐藏的窗体字段(http://www.ddvip.net/web/aspnet/technique/22.htm

QueryString

  QueryString对象中保存的数据由单独的用户使用。它的生命周期可能只有一个请求那么短,也可能有用户使用应用程序的时间那么长(如果构造正确的话)。这类数据一般小于1KB。QueryString中的数据在URL中传递,对于用户来说是可见的,因此你能猜到,使用这种技术时,敏感的数据或可用于控制应用程序的数据需要加密。

  也就是说,QueryString是在ASP.NET Web窗体间发送信息的一条很好的途径。例如,如果有一个含有产品列表的数据表格(DataGrid),并且在表格上有一个链接导向产品的细节页面,使用QueryString就是理想的,可以把产品的ID包含在链接到产品细节页面的QueryString中(例如productdetails.aspx?id=4)。使用QueryStrings的另一个好处是页面的状态包含在URL中。这意味着用户可以把某个通过QueryStrings建立的窗体放入他的收藏夹中。当它们作为收藏返回到页面时,将与作收藏的时候一样。很明显这只在页面不依赖QueryString外的所有状态和不作任何改变的时候有作用。

  敏感数据,以及任何不希望用户操作的变量应该避免出现在此处(除非加密使用户不能阅读)。并且URL中不合法的字符必须使用Server.UrlEncode编码。当处理单个ASP.NET页面时,对维护状态来说ViewState是比QueryString好的选择。对于长期的数据存储,Cookie、Sessions或Cache都比QueryStrings更加适于作为数据容器。

Querystring.aspx.cs

private void Page_Load(object sender, System.EventArgs e)

{

// 检索cookie的值

if(Request.QueryString.HasKeys())

{

lblResult.Text = "The values of the <b>" + txtName.Text +

"</b> querystring parameter are:<br>";

foreach(string key in Request.QueryString.Keys)

{

lblResult.Text += "[" + key + " = " +

Request.QueryString[key].ToString() + "]<br>";

}

}

}

private void btnSubmit_Click(object sender, System.EventArgs e)

{

if(IsValid)

{

string url = "querystring.aspx?";

foreach(string key in Request.QueryString.Keys)

{

url += key + "=" + Request.QueryString[key].ToString() + "&";

}

Response.Redirect(url + txtName.Text + "=" +

Server.UrlEncode(txtValue.Text));

}

}

Sessions

  Sessions数据对于特定的用户是特定的。它的生存期是用户持续请求的时间加上后来一段时间(一般是20分钟)。Sessions可以保持或大或小的数据量,但是如果应用程序用于成百上千的用户,那么总共的存储应该保持最小。

  不幸的是在传统的ASP中Sessions对象的名声很不好,因为它把应用程序约束到特定的计算机上,阻碍了用户分组和Web范围的可伸缩性。在ASP.NET中几乎没有这些问题,因为改变Sessions保存的位置很简单。在默认情况下(性能最好的情况),Sessions数据仍然保存在本地Web服务器的内存中,但是ASP.NET支持使用外部状态服务器或数据库管理Sessions数据。

  使用Sessions对象很简单,并且它的语法与传统ASP相同。但是Sessions对象是保存用户数据的方法中效率很低的一种,因为即使用户停止使用应用程序后它仍然保持在内存中一段时间。这对于非常繁忙的站点的可伸缩性有严重的影响。其它的选择允许对释放内存的更多的控制,例如Cache对象也许更适合大量的大数据值。并且在默认情况下ASP.NET Sessionss依赖于cookie,因此如果用户禁止或不支持cookie,Sessionss就不能工作,但是可以配置Sessionss支持cookie无关。对于小的数据量,Sessionss对象是保存只需要在用户当前对话中保持的特定数据的极好位置。

private void btnSubmit_Click(object sender, System.EventArgs e)

{

 if(IsValid)

 {

  // 设置Sessions值

  Sessions[txtName.Text] = txtValue.Text;

      //读取和显示刚才的设置

  lblResult.Text = "The value of <b>" + txtName.Text + "</b> in the Sessions object is <b>" + Sessions[txtName.Text].ToString() + "</b>";

 }

}

该Web窗体与Application对象中使用的几乎相同,当允许页面追踪时Sessions集合的内容也是可见的。

你需要记住的是即使没有使用,Sessionss也会有应用程序开销。把Sessionss状态设置为只读的也可以优化只需要读而不需要写数据的页面。可以使用下面两种途径之一来配置Sessionss:

<%@ Page EnableSessionsstate="false" %>

<%@ Page EnableSessionsstate="readonly" %>

  ASP.NET Sessionss可以在Web.config或Machine.config中的Sessionsstate元素中配置。下面是在 Web.config中的设置的例子:

<Sessionsstate timeout="10" cookieless="false" mode="Inproc" />

Cache

  Cache对象用于单个用户、一组用户或所有的用户。这种数据为多个请求保持。它可以保持很长时间,但是不能超过应用程序重新启动的时间,并且数据的终止基于时间或者其它的依赖关系。它可以高效率地保持大量或少量地数据。

  Cache 是ASP.NET中最"酷"的对象之一。它提供了难以置信的灵活性、通用性和性能,因此在ASP.NET应用程序中它通常是比Application或Sessions更好的保持数据的对象。本文没有详细介绍Cache对象的使用方法,但是仍然可以说它是一个万能对象。与其它的集合对象相似,它是一个简单的名称-值集合,但是通过使用指定特定用户的键值可以缓存特定用户的值。同样你可以缓存不同的相关数据的多个数据集,例如几个有键(如fordcars 、 chevycars、gmcars)的汽车集合。Cache中的数据可以给定一个绝对的、可变的或基于文件的终止时间。它们也实现了一个回调功能,在被缓存的值从缓存中提取时被调用,这个功能很有用,因为接着你能检查它是否为最新的数据变量,如果不是(或数据源不可用),就重新缓存被终止的值。

  添加和访问缓存中值的语法与先前谈到的相似。但是Cache给访问集合内容的标准索引器方法作了补充,它支持多种方法,允许对被缓存数据的更多的控制。最频繁使用的方法是Insert,它支持几种重载,允许你指定依赖、超时值、优先级和回调。

// 给缓存添加项

Cache["myKey"] = myValue;

// 从缓存中读取项

Response.Write(Cache["myKey"]);

// 把CacheDuration增加10秒并把项添加到缓存中

Cache.Insert("myKey",myValue, null, System.DateTime.Now.AddSeconds(10),

System.Web.Caching.Cache.NoSlidingExpiration);

 Context

  Context对象保持单个用户、单个请求的数据,并且数据只在该请求期间保持。Context容器可以保持大量的数据,但是典型的情况下是保存小的数据片,因为它经常通过global.asax中的某个处理方法为每个请求实现。

  Context容器(从Page对象访问或使用System.Web.HttpContext.Current)被提供用于保持需要在不同的HttpModules和HttpHandlers之间传递的值。它也可以用于保持某个完整请求的相应信息。例如,IbuySpy入口在global.asax中的Application_BeginRequest事件过程中给容器填满了许多配置信息。注意这只在当前请求中可用,如果你希望在下一个请求中也能使用,请考虑使用ViewState。

  从Context集合中设置和获取数据使用的语法与前面讨论的其它集合对象(如Application、Sessions和 Cache)的相似。

// 给Context添加项

Context.Items["myKey"] = myValue;

// 从Context中读取项

Response.Write(Context["myKey"]);

ViewState

  ViewState为单个用户保持状态信息,保持期为ASPX页面工作时间。ViewState容器可以保持大量的数据,但是必须小心管理ViewState的大小,因为它增加了每个请求和回应的下载(download)大小。

  ViewState是ASP.NET中的一个新容器,也许你已经使用它了,但是你可能还是不了解它。这是因为所有的内建Web控件都使用ViewState在页面回发(postback)间保持自己的值。但是你必须小心,因为它影响应用程序的性能。影响的大小依赖于回发之间使用ViewState的多少--对大多数Web窗体来说数量非常小。

  确定某个页面上每个控件使用的ViewState的数量最简单的方法是打开页面追踪并检查每个控件负载了多少个ViewState。如果某个特定控件不需要在回发之间保持数据,请通过把EnableViewState设置为false关闭该对象的ViewState。你也可以通过在浏览器中查看的HTML源并检查隐藏窗体字段__VIEWSTATE来确定某个给定的ASP.NET页面ViewState的总共大小。注意这些内容都是使用Base64编码的,用于放置偶然的查看和维护。ViewState也可以通过给@Page指令添加EnableViewState="false"在整个页面中禁止。

  典型的Web窗体不需要直接维护ViewState。但是如果你建立自定义Web控件,就需要了解它是怎样工作的,并为你的控件实现它,这样该控件的工作方式才能与随ASP.NET发布的Web控件同样地工作。向ViewState读取或写入值都可以通过上面讨论地其它集合对象的语法完成:

// 给ViewState添加项

ViewState["myKey"] = myValue;

//从Context读取项

Response.Write(ViewState["myKey"]);

 

  当建立自定义Web控件时,你也许希望它们有ViewState的好处。这在控件的属性层可以简单实现。下面演示了怎样保存一个简单的自定义控件的PersonName属性到ViewState中,并在该控件的Render方法中使用它。

namespace MSDN.StateManagement

{

 public class HelloPerson : System.Web.UI.Control

 {

  public string PersonName

  {

   get

   {

    string s = (string)ViewState["PersonName"];

    return ((s == null) ? "" : s);

   }

   set

   {

    ViewState["PersonName"] = value;

   }

  }

  protected override void Render(System.Web.UI.HtmlTextWriter writer)

  {

   writer.Write("Hello " + PersonName);

  }

 }

}

Web.configMachine.config文件

  这些文件中的数据对于某个应用程序的所有用户来说都可以使用。Web.config文件中存储的数据可用于应用程序的整个生命周期。这些数据一般很小,该对象一般用于保持文件位置和数据库连接的字符串。大的数据片最好保存在其它位置。

  作为其它多样集合对象的补充,ASP.NET引入了一组XML配置文件用于管理应用程序甚至于整个服务器的很多设置。每个ASP.NET应用程序使用Web.config文件来设置它的许多属性,每个服务器在系统文件夹下有一个作为应用程序基础的Machine.config文件。这些设置都作为默认值使用,除非重载。作为保存配置数据的补充,这些文件可以保存应用程序(或多个应用程序)需要的数据。

  无论什么时候应用程序启动都会读取配置信息,接着这些信息被缓冲。由于被缓冲了,应用程序可以快速读取它们,因此不需要考虑应用程序的瓶颈,因为它经常执行某个文本文件的一些整型信息。此外,某个应用程序的Web.config的改变将导致应用程序重新启动。这确保了对配置文件信息的修改立即反映到应用程序中。

  数据库连接信息,默认图像路径和XML数据文件路径是通常保存在Web.config文件中的数据片。在Web.config文件中保存数据的语法如下,在理想的情况下你也许希望使用集成的SQL身分验证:

<configuration>

<!-应用程序特殊设置 -->

<appSettings>

<add key="connectionString" value="server=myDBServer;

uid=myUID;pwd=myPassword;database=myDB" />

</appSettings>

<system.web>

<!-所有的web设置 -->

</system.web>

</configuration> 

  为了访问ASP.NET页面中的值,可以使用ConfigurationSettings集合,它在System.Configuration名字空间中。下面的简单例子演示了怎样提取前面的连接字符串到一个本地变量中:

using System.Configuration;

ooo

String strConnString =

ConfigurationSettings.AppSettings["connectionString"];

  给System.Configuration名字空间添加一个引用减少了引用这些值的代码数量。因为对Web.config或 Machine.config的修改将导致应用程序立即重新启动,典型情况下这些值只由服务器系统管理员手动修改。因此你可以认为这些文件是保存只读数据而不是应用程序中修改的数据的好位置。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: